From 7cae09454309cdd31d63bd46415d3b349a8ccd38 Mon Sep 17 00:00:00 2001 From: mrq Date: Sun, 14 Mar 2021 00:00:00 -0600 Subject: [PATCH] Commit for 2021.03.14.7z --- Makefile | 2 +- bin/data/shaders/display/subpass.frag.glsl | 44 +- bin/data/shaders/gltf/base.frag.glsl | 2 +- .../shaders/gui/{frag.glsl => base.frag.glsl} | 0 .../shaders/gui/{vert.glsl => base.vert.glsl} | 0 engine/inc/uf/ext/gltf/graph.h | 2 +- engine/inc/uf/ext/lua/lua.inl | 7 +- engine/inc/uf/ext/opengl/commands.h | 2 +- engine/inc/uf/ext/opengl/ogl.h | 24 +- engine/inc/uf/ext/opengl/opengl.h | 1 + engine/inc/uf/ext/opengl/texture.h | 4 +- engine/inc/uf/ext/vulkan/texture.h | 4 +- engine/inc/uf/ext/vulkan/vulkan.h | 1 + engine/inc/uf/utils/graphic/mesh.h | 1 - engine/inc/uf/utils/image/atlas.h | 38 +- engine/inc/uf/utils/math/matrix.h | 4 +- engine/inc/uf/utils/math/matrix/pod.inl | 16 +- engine/src/engine/asset/asset.cpp | 4 +- engine/src/engine/behavior/behavior.cpp | 9 +- engine/src/engine/object/behavior.cpp | 33 +- engine/src/engine/scene/scene.cpp | 8 +- engine/src/ext/gltf/gltf.cpp | 18 +- engine/src/ext/gltf/graph.cpp | 109 ++- engine/src/ext/lua/lua.cpp | 214 +++-- engine/src/ext/lua/usertypes/asset.cpp | 29 +- engine/src/ext/lua/usertypes/audio.cpp | 44 +- engine/src/ext/lua/usertypes/camera.cpp | 46 +- engine/src/ext/lua/usertypes/matrix.cpp | 49 +- engine/src/ext/lua/usertypes/object.cpp | 326 ++++---- engine/src/ext/lua/usertypes/quaternion.cpp | 126 +-- engine/src/ext/lua/usertypes/timer.cpp | 23 +- engine/src/ext/lua/usertypes/transform.cpp | 57 +- engine/src/ext/lua/usertypes/vector.cpp | 194 +++-- engine/src/ext/opengl/commands.cpp | 54 +- engine/src/ext/opengl/graphic.cpp | 58 +- engine/src/ext/opengl/opengl.cpp | 3 + engine/src/ext/opengl/rendermode.cpp | 60 +- engine/src/ext/opengl/rendermodes/base.cpp | 5 +- .../src/ext/opengl/rendermodes/deferred.cpp | 3 +- .../ext/opengl/rendermodes/rendertarget.cpp | 22 +- engine/src/ext/opengl/texture.cpp | 20 +- engine/src/ext/vulkan/rendermode.cpp | 26 - .../ext/vulkan/rendermodes/rendertarget.cpp | 13 +- engine/src/ext/vulkan/texture.cpp | 71 +- engine/src/ext/vulkan/vulkan.cpp | 1 + engine/src/ext/xatlas/xatlas.cpp | 4 +- engine/src/utils/image/atlas.cpp | 326 +++----- engine/src/utils/image/image.cpp | 20 +- engine/src/utils/mesh/grid.cpp | 4 +- ext/behaviors/baking/behavior.cpp | 4 +- ext/behaviors/light/behavior.cpp | 26 +- ext/gui/behavior.cpp | 768 +++++++++--------- ext/gui/behavior.h | 42 + ext/gui/gui.h | 1 + ext/gui/manager/behavior.cpp | 76 +- ext/gui/manager/behavior.h | 3 + ext/main.cpp | 7 - makefiles/win64.gcc.make | 2 +- 58 files changed, 1632 insertions(+), 1428 deletions(-) rename bin/data/shaders/gui/{frag.glsl => base.frag.glsl} (100%) rename bin/data/shaders/gui/{vert.glsl => base.vert.glsl} (100%) diff --git a/Makefile b/Makefile index 0ebcdf93..96f5768c 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ ifneq (,$(findstring win64,$(ARCH))) FLAGS += DEPS += -lgdi32 else ifneq (,$(findstring dreamcast,$(ARCH))) - REQ_DEPS += opengl gldc json:nlohmann bullet lua # freetype png meshoptimizer ogg openal draco luajit ultralight-ux ncurses curl openvr discord + REQ_DEPS += opengl gldc json:nlohmann bullet lua freetype png # meshoptimizer ogg openal draco luajit ultralight-ux ncurses curl openvr discord endif ifneq (,$(findstring vulkan,$(REQ_DEPS))) FLAGS += -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN diff --git a/bin/data/shaders/display/subpass.frag.glsl b/bin/data/shaders/display/subpass.frag.glsl index c4a2d04c..f8eefc4c 100644 --- a/bin/data/shaders/display/subpass.frag.glsl +++ b/bin/data/shaders/display/subpass.frag.glsl @@ -250,23 +250,23 @@ float random(vec3 seed, int i){ return fract(sin(dot_product) * 43758.5453); } -float shadowFactor( Light light, uint shadowMap ) { +float shadowFactor( Light light, uint shadowMap, float def ) { vec4 positionClip = light.projection * light.view * vec4(position.world, 1.0); positionClip.xyz /= positionClip.w; - if ( positionClip.x < -1 || positionClip.x >= 1 ) return 0.0; - if ( positionClip.y < -1 || positionClip.y >= 1 ) return 0.0; - if ( positionClip.z <= 0 || positionClip.z >= 1 ) return 0.0; + if ( positionClip.x < -1 || positionClip.x >= 1 ) return def; //0.0; + if ( positionClip.y < -1 || positionClip.y >= 1 ) return def; //0.0; + if ( positionClip.z <= 0 || positionClip.z >= 1 ) return def; //0.0; float factor = 1.0; // spot light - if ( light.type == 2 || light.type == 3 ) { + if ( light.type == 1 || light.type == 2 ) { float dist = length( positionClip.xy ); - if ( dist > 0.5 ) return 0.0; + if ( dist > 0.5 ) return def; //0.0; // spot light with attenuation - if ( light.type == 3 ) { + if ( light.type == 2 ) { factor = 1.0 - (pow(dist * 2,2.0)); } } @@ -578,7 +578,7 @@ float mipLevel( in vec2 uv ) { return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc))); } bool validTextureIndex( int textureIndex ) { - return 0 <= textureIndex && textureIndex < ubo.textures; + return 0 <= textureIndex; // && textureIndex < ubo.textures; } vec4 resolve( subpassInputMS t ) { int samples = int(ubo.msaa); @@ -698,30 +698,25 @@ void main() { bool useLightmap = 0 <= material.indexLightmap; if ( useLightmap ) { fragColor = C.rgb + ubo.ambient.rgb; - } else { - fragColor = C.rgb * ubo.ambient.rgb * AO; - } { - /* - fragColor = C.rgb + ubo.ambient.rgb; - float factor = 0.0; - int total = 0; + /* + float totalShadows = 0.0; + float totalLights = 0.0; + for ( uint i = 0; i < ubo.lights; ++i ) { Light light = lights[i]; + if ( light.power <= 0.001 ) continue; - if ( !validTextureIndex(light.mapIndex) ) continue; vec3 lightPositionWorld = light.position.xyz; light.position.xyz = vec3(ubo.matrices.view[inPushConstantPass] * vec4(light.position.xyz, 1)); - factor += (1 - shadowFactor( light, light.mapIndex, 1.0 )) * 3; - ++total; - } - if ( total > 0 ) { - float darken = 1 - factor / total; - fragColor *= darken; + ++totalLights; + if ( !validTextureIndex(light.mapIndex) ) continue; + totalShadows += shadowFactor( light, light.mapIndex, 1.0 ); } + fragColor = vec3(totalShadows / totalLights); + */ } else { fragColor = C.rgb * ubo.ambient.rgb * AO; - */ for ( uint i = 0; i < ubo.lights; ++i ) { Light light = lights[i]; @@ -731,7 +726,7 @@ void main() { light.position.xyz = vec3(ubo.matrices.view[inPushConstantPass] * vec4(light.position.xyz, 1)); if ( validTextureIndex(light.mapIndex) ) { - float factor = shadowFactor( light, light.mapIndex ); + float factor = shadowFactor( light, light.mapIndex, 0.0 ); light.power *= factor; litFactor += light.power; } @@ -747,6 +742,7 @@ void main() { fog(rayO, rayD, fragColor, litFactor); /* + if ( (ubo.mode.type & (0x1 << 0)) == (0x1 << 0) ) { //dither1(fragColor); fragColor += dither2(); diff --git a/bin/data/shaders/gltf/base.frag.glsl b/bin/data/shaders/gltf/base.frag.glsl index deb9cfe1..4dfe0f77 100644 --- a/bin/data/shaders/gltf/base.frag.glsl +++ b/bin/data/shaders/gltf/base.frag.glsl @@ -112,7 +112,7 @@ void main() { } if ( C.a == 0 ) discard; } -#if 0 +#if 1 if ( validTextureIndex( material.indexLightmap ) ) { #if UF_DEFERRED_SAMPLING outUvs = inSt; diff --git a/bin/data/shaders/gui/frag.glsl b/bin/data/shaders/gui/base.frag.glsl similarity index 100% rename from bin/data/shaders/gui/frag.glsl rename to bin/data/shaders/gui/base.frag.glsl diff --git a/bin/data/shaders/gui/vert.glsl b/bin/data/shaders/gui/base.vert.glsl similarity index 100% rename from bin/data/shaders/gui/vert.glsl rename to bin/data/shaders/gui/base.vert.glsl diff --git a/engine/inc/uf/ext/gltf/graph.h b/engine/inc/uf/ext/gltf/graph.h index bc2db227..1ed2eced 100644 --- a/engine/inc/uf/ext/gltf/graph.h +++ b/engine/inc/uf/ext/gltf/graph.h @@ -57,7 +57,7 @@ namespace pod { ext::gltf::load_mode_t mode; uf::Serializer metadata; - uf::Atlas* atlas = NULL; + uf::Atlas atlas; std::vector images; std::vector samplers; std::vector textures; diff --git a/engine/inc/uf/ext/lua/lua.inl b/engine/inc/uf/ext/lua/lua.inl index be5e8c59..c72ac197 100644 --- a/engine/inc/uf/ext/lua/lua.inl +++ b/engine/inc/uf/ext/lua/lua.inl @@ -12,6 +12,7 @@ namespace {\ #define UF_LUA_REGISTER_USERTYPE_DEFINE_RT(k, v) usertype[#k] = v; #define UF_LUA_REGISTER_USERTYPE_MEMBER_RT(member) usertype[UF_NS_GET_LAST(member)] = &member; +#define UF_LUA_REGISTER_USERTYPE_MEMBER_FUN_RT(member) usertype[UF_NS_GET_LAST(member)] = UF_LUA_C_FUN(member); #define UF_LUA_REGISTER_USERTYPE_END() \ });\ @@ -29,4 +30,8 @@ namespace {\ } #define UF_LUA_REGISTER_USERTYPE_DEFINE(k, v) #k, v -#define UF_LUA_REGISTER_USERTYPE_MEMBER(member) UF_NS_GET_LAST(member), &member \ No newline at end of file +#define UF_LUA_REGISTER_USERTYPE_MEMBER(member) UF_NS_GET_LAST(member), &member +#define UF_LUA_REGISTER_USERTYPE_MEMBER_FUN(member) UF_NS_GET_LAST(member), UF_LUA_C_FUN(member) + +#define UF_LUA_C_FUN(x) sol::c_call +#define UF_LUA_WRAP_FUN(x) sol::c_call> \ No newline at end of file diff --git a/engine/inc/uf/ext/opengl/commands.h b/engine/inc/uf/ext/opengl/commands.h index b0885535..78115ad8 100644 --- a/engine/inc/uf/ext/opengl/commands.h +++ b/engine/inc/uf/ext/opengl/commands.h @@ -119,7 +119,7 @@ namespace ext { void end(); size_t size() const; protected: - void bindUniform( const Buffer::Descriptor& descriptor ); + pod::Matrix4f bindUniform( const Buffer::Descriptor& descriptor ); void drawIndexed( const InfoDraw& ); // void draw( const InfoDraw&, const Info&, const std::vector& = {} ); // void drawIndexed( const InfoDraw&, const Info&, const Info&, const std::vector& = {} ); diff --git a/engine/inc/uf/ext/opengl/ogl.h b/engine/inc/uf/ext/opengl/ogl.h index b35f6ccd..eacee951 100644 --- a/engine/inc/uf/ext/opengl/ogl.h +++ b/engine/inc/uf/ext/opengl/ogl.h @@ -48,15 +48,23 @@ #define GL_DEBUG_MESSAGE(...) UF_DEBUG_MSG(__VA_ARGS__); #define GL_VALIDATION_MESSAGE(...) if ( ext::opengl::settings::validation ) GL_DEBUG_MESSAGE(__VA_ARGS__); -#define GL_ERROR_CHECK(f) { \ - {f;} \ - GLenum res = glGetError(); \ - if (res != GL_NO_ERROR) { \ - std::string errorString = ext::opengl::errorString( res ); \ - GL_VALIDATION_MESSAGE("[Validation Error] " << #f << ": " << errorString); \ - } \ -} +#if UF_ENV_DREAMCAST + #define GL_VALIDATION_ENABLED 0 +#else + #define GL_VALIDATION_ENABLED 1 +#endif +#if GL_VALIDATION_ENABLED + #define GL_ERROR_CHECK(f) { \ + {f;} \ + if ( ext::opengl::settings::validation ) { \ + GLenum res = glGetError(); \ + if (res != GL_NO_ERROR) GL_DEBUG_MESSAGE("[Validation Error] " << #f << ": " << ext::opengl::errorString( res )); \ + } \ + } +#else + #define GL_ERROR_CHECK(f) {f;} +#endif #if 0 #define GL_MUTEX_LOCK() ext::opengl::mutex.lock(); #define GL_MUTEX_UNLOCK() ext::opengl::mutex.unlock(); diff --git a/engine/inc/uf/ext/opengl/opengl.h b/engine/inc/uf/ext/opengl/opengl.h index 8434f8cf..ed06cfa5 100644 --- a/engine/inc/uf/ext/opengl/opengl.h +++ b/engine/inc/uf/ext/opengl/opengl.h @@ -36,6 +36,7 @@ namespace ext { extern UF_API bool multiview; extern UF_API bool vsync; extern UF_API bool hdr; + extern UF_API bool frustrumCull; } namespace formats { diff --git a/engine/inc/uf/ext/opengl/texture.h b/engine/inc/uf/ext/opengl/texture.h index 9215fe5a..e6c69d9c 100644 --- a/engine/inc/uf/ext/opengl/texture.h +++ b/engine/inc/uf/ext/opengl/texture.h @@ -85,11 +85,11 @@ namespace ext { enums::Format::type_t format = enums::Format::R8G8B8A8_UNORM ); void loadFromImage( - uf::Image& image, + const uf::Image& image, enums::Format::type_t format = enums::Format::R8G8B8A8_UNORM ); void loadFromImage( - uf::Image& image, + const uf::Image& image, Device& device, enums::Format::type_t format = enums::Format::R8G8B8A8_UNORM ); diff --git a/engine/inc/uf/ext/vulkan/texture.h b/engine/inc/uf/ext/vulkan/texture.h index df41ed06..383a3bac 100644 --- a/engine/inc/uf/ext/vulkan/texture.h +++ b/engine/inc/uf/ext/vulkan/texture.h @@ -93,14 +93,14 @@ namespace ext { VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ); void loadFromImage( - uf::Image& image, + const uf::Image& image, Device& device, VkFormat format = VK_FORMAT_R8G8B8A8_UNORM, VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ); void loadFromImage( - uf::Image& image, + const uf::Image& image, VkFormat format = VK_FORMAT_R8G8B8A8_UNORM, VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT, VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL diff --git a/engine/inc/uf/ext/vulkan/vulkan.h b/engine/inc/uf/ext/vulkan/vulkan.h index 03d266a3..e304c6e9 100644 --- a/engine/inc/uf/ext/vulkan/vulkan.h +++ b/engine/inc/uf/ext/vulkan/vulkan.h @@ -63,6 +63,7 @@ namespace ext { extern UF_API bool multiview; extern UF_API bool vsync; extern UF_API bool hdr; + extern UF_API bool frustrumCull; } namespace formats { diff --git a/engine/inc/uf/utils/graphic/mesh.h b/engine/inc/uf/utils/graphic/mesh.h index f0f09158..131a5808 100644 --- a/engine/inc/uf/utils/graphic/mesh.h +++ b/engine/inc/uf/utils/graphic/mesh.h @@ -63,7 +63,6 @@ namespace pod { namespace uf { typedef BaseMesh ColoredMesh; typedef BaseMesh Mesh; - typedef BaseMesh GuiMesh; typedef BaseMesh LineMesh; template diff --git a/engine/inc/uf/utils/image/atlas.h b/engine/inc/uf/utils/image/atlas.h index 0916d6ea..caeb192a 100644 --- a/engine/inc/uf/utils/image/atlas.h +++ b/engine/inc/uf/utils/image/atlas.h @@ -1,39 +1,48 @@ #pragma once #include -#include #include namespace uf { class UF_API Atlas { public: + typedef std::string hash_t; struct Identifier { size_t index; + hash_t hash; + }; + struct Tile { + uf::Image image; + Identifier identifier = {0,""}; + pod::Vector2ui size = {}; + pod::Vector2ui coord = {}; }; typedef std::vector images_t; - typedef Identifier identifier_t; - typedef BinPack2D::CanvasArray atlas_t; + typedef std::unordered_map atlas_t; protected: - uf::Image m_image; - images_t m_images; - atlas_t m_atlas; + uf::Image m_atlas; + atlas_t m_tiles; public: - void addImage( const uf::Image&, bool = false ); - void addImage( uf::Image&&, bool = false ); - void addImage( const uint8_t*, const pod::Vector2ui&, std::size_t, std::size_t, bool = false, bool = false ); + hash_t addImage( const uf::Image&, bool = false ); + hash_t addImage( uf::Image&&, bool = false ); + hash_t addImage( const uint8_t*, const pod::Vector2ui&, std::size_t, std::size_t, bool = false, bool = false ); void generate(float padding = 1); - void generate( const images_t&, float padding = 1); - void clear(); + void generate( const std::vector&, float padding = 1); + void clear(bool = true); + bool generated() const; + pod::Vector2f mapUv( const pod::Vector2f&, const hash_t& ); pod::Vector2f mapUv( const pod::Vector2f&, size_t ); pod::Vector3f mapUv( const pod::Vector3f& ); uf::Image& getAtlas(); - images_t& getImages(); - const images_t& getImages() const; + const uf::Image& getAtlas() const; + + atlas_t& getImages(); + const atlas_t& getImages() const; }; - +#if 0 class UF_API HashAtlas { public: typedef std::string hash_t; @@ -65,4 +74,5 @@ namespace uf { images_t& getImages(); const images_t& getImages() const; }; +#endif } \ No newline at end of file diff --git a/engine/inc/uf/utils/math/matrix.h b/engine/inc/uf/utils/math/matrix.h index 4d10b851..af963425 100644 --- a/engine/inc/uf/utils/math/matrix.h +++ b/engine/inc/uf/utils/math/matrix.h @@ -63,8 +63,8 @@ namespace uf { template pod::Matrix multiply( const pod::Matrix& left, const pod::Matrix& right ); // Multiplies two matrices of same type and size together template T /*UF_API*/ transpose( const T& matrix ); // Flip sign of all components template T /*UF_API*/ inverse( const T& matrix ); // Flip sign of all components - template pod::Vector3t multiply( const pod::Matrix4t& mat, const pod::Vector3t& vector, T w = 1 ); - template pod::Vector4t multiply( const pod::Matrix4t& mat, const pod::Vector4t& vector ); + template pod::Vector3t multiply( const pod::Matrix4t& mat, const pod::Vector3t& vector, T w = 1, bool = false ); + template pod::Vector4t multiply( const pod::Matrix4t& mat, const pod::Vector4t& vector, bool = false ); template T /*UF_API*/ multiplyAll( const T& matrix, typename T::type_t scalar ); template T /*UF_API*/ add( const T& lhs, const T& rhs ); diff --git a/engine/inc/uf/utils/math/matrix/pod.inl b/engine/inc/uf/utils/math/matrix/pod.inl index 651a29fa..99ce627e 100644 --- a/engine/inc/uf/utils/math/matrix/pod.inl +++ b/engine/inc/uf/utils/math/matrix/pod.inl @@ -410,21 +410,25 @@ template T uf::matrix::inverse( const T& matrix ) { template pod::Matrix uf::matrix::multiply( T& left, const T& right ) { return left = uf::matrix::multiply((const T&) left, right); } -template pod::Vector3t uf::matrix::multiply( const pod::Matrix4t& mat, const pod::Vector3t& vector, T w ) { - return uf::matrix::multiply( mat, pod::Vector4t{ vector[0], vector[1], vector[2], w } ); +template pod::Vector3t uf::matrix::multiply( const pod::Matrix4t& mat, const pod::Vector3t& vector, T w, bool div ) { + return uf::matrix::multiply( mat, pod::Vector4t{ vector[0], vector[1], vector[2], w }, div ); } -template pod::Vector4t uf::matrix::multiply( const pod::Matrix4t& mat, const pod::Vector4t& vector ) { +template pod::Vector4t uf::matrix::multiply( const pod::Matrix4t& mat, const pod::Vector4t& vector, bool div ) { #if UF_ENV_DREAMCAST MATH_Load_XMTRX( (ALL_FLOATS_STRUCT*) &mat[0] ); - auto res = MATH_Matrix_Transform( vector[0], vector[1], vector[2], vector[3] ); - return *((pod::Vector4t*) &res); + auto t = MATH_Matrix_Transform( vector[0], vector[1], vector[2], vector[3] ); + auto res = *((pod::Vector4t*) &t); + if ( div && res.w > 0 ) res /= res.w; + return res; #endif - return { + auto res = pod::Vector4t{ vector[0] * mat[0] + vector[1] * mat[4] + vector[2] * mat[8] + vector[3] * mat[12], vector[0] * mat[1] + vector[1] * mat[5] + vector[2] * mat[9] + vector[3] * mat[13], vector[0] * mat[2] + vector[1] * mat[6] + vector[2] * mat[10] + vector[3] * mat[14], vector[0] * mat[3] + vector[1] * mat[7] + vector[2] * mat[11] + vector[3] * mat[15] }; + if ( div && res.w > 0 ) res /= res.w; + return res; } // Flip sign of all components template T& uf::matrix::invert( T& matrix ) { diff --git a/engine/src/engine/asset/asset.cpp b/engine/src/engine/asset/asset.cpp index d0ae86ba..bff1125f 100644 --- a/engine/src/engine/asset/asset.cpp +++ b/engine/src/engine/asset/asset.cpp @@ -175,9 +175,9 @@ std::string uf::Asset::load( const std::string& uri, const std::string& hash, co // force disable use of a texture atlas, for now metadata[uri]["flags"]["ATLAS"] = false; metadata[uri]["flags"]["SEPARATE"] = true; - metadata[uri]["flags"]["NORMALS"] = true; + // metadata[uri]["flags"]["NORMALS"] = true; #else - metadata[uri]["flags"]["ATLAS"] = true; + // metadata[uri]["flags"]["ATLAS"] = true; #endif ext::gltf::load_mode_t LOAD_FLAGS = 0; #define LOAD_FLAG(name)\ diff --git a/engine/src/engine/behavior/behavior.cpp b/engine/src/engine/behavior/behavior.cpp index e6521151..0788dd20 100644 --- a/engine/src/engine/behavior/behavior.cpp +++ b/engine/src/engine/behavior/behavior.cpp @@ -88,8 +88,15 @@ void uf::Behaviors::tick() { uf::Object& self = *((uf::Object*) this); if ( !self.isValid() ) return; // UF_TIMER_TRACE_INIT(); - UF_BEHAVIOR_POLYFILL(tick) +// UF_BEHAVIOR_POLYFILL(tick) // UF_TIMER_TRACE(self.getName() << ": " << self.getUid()); + +// UF_TIMER_MULTITRACE_START("==== START TICKING BEHAVIORS ===="); + for ( auto& behavior : this->m_behaviors ) { + behavior.tick(self); +// UF_TIMER_MULTITRACE(behavior.type); + } +// UF_TIMER_MULTITRACE_END("==== END TICKING BEHAVIORS ===="); } void uf::Behaviors::render() { uf::Object& self = *((uf::Object*) this); diff --git a/engine/src/engine/object/behavior.cpp b/engine/src/engine/object/behavior.cpp index 178619b3..a94c1e2e 100644 --- a/engine/src/engine/object/behavior.cpp +++ b/engine/src/engine/object/behavior.cpp @@ -167,6 +167,10 @@ void uf::ObjectBehavior::destroy( uf::Object& self ) { graphic.destroy(); uf::renderer::states::rebuild = true; } + if ( this->hasComponent() ) { + auto& atlas = this->getComponent(); + atlas.clear(); + } } void uf::ObjectBehavior::tick( uf::Object& self ) { // listen for metadata file changes @@ -201,18 +205,29 @@ void uf::ObjectBehavior::tick( uf::Object& self ) { if ( ext::json::isObject( metadata ) ) queue = newQueue; } #else + auto& metadata = this->getComponent(); - { - auto& queue = metadata.hooks.queue; - if ( !uf::Object::timer.running() ) uf::Object::timer.start(); - float curTime = uf::Object::timer.elapsed().asDouble(); - for ( auto it = queue.begin(); it != queue.end(); ) { - auto& q = *it; - if ( q.timeout < curTime ) { this->callHook( q.name, q.payload ); it = queue.erase( it ); } - else ++it; - } + auto& queue = metadata.hooks.queue; + if ( !uf::Object::timer.running() ) uf::Object::timer.start(); + float curTime = uf::Object::timer.elapsed().asDouble(); +#if 1 + decltype(metadata.hooks.queue) unprocessed; + unprocessed.reserve( metadata.hooks.queue.size() ); + + decltype(metadata.hooks.queue) executeQueue; + 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 ); + queue = std::move(unprocessed); +#else + for ( auto it = queue.begin(); it != queue.end(); ) { + auto& q = *it; + if ( q.timeout < curTime ) { this->callHook( q.name, q.payload ); it = queue.erase( it ); } + else ++it; } #endif +#endif } void uf::ObjectBehavior::render( uf::Object& self ) {} #undef this diff --git a/engine/src/engine/scene/scene.cpp b/engine/src/engine/scene/scene.cpp index eb422a54..9983dc10 100644 --- a/engine/src/engine/scene/scene.cpp +++ b/engine/src/engine/scene/scene.cpp @@ -97,19 +97,19 @@ std::vector uf::scene::generateGraph() { void uf::scene::tick() { auto graph = uf::scene::generateGraph(); -// UF_TIMER_MULTITRACE_START("==== START RENDER ===="); +// UF_TIMER_MULTITRACE_START("==== START TICK ===="); for ( auto it = graph.rbegin(); it != graph.rend(); ++it ) { (*it)->tick(); -// UF_TIMER_MULTITRACE_START((*it)->getName() << ": " << (*it)->getUid()); +// UF_TIMER_MULTITRACE((*it)->getName() << ": " << (*it)->getUid()); } -// UF_TIMER_MULTITRACE_END("==== END RENDER ===="); +// UF_TIMER_MULTITRACE_END("==== END TICK ===="); } void uf::scene::render() { auto graph = uf::scene::generateGraph(); // UF_TIMER_MULTITRACE_START("==== START RENDER ===="); for ( auto it = graph.rbegin(); it != graph.rend(); ++it ) { (*it)->render(); -// UF_TIMER_MULTITRACE_START((*it)->getName() << ": " << (*it)->getUid()); +// UF_TIMER_MULTITRACE((*it)->getName() << ": " << (*it)->getUid()); } // UF_TIMER_MULTITRACE_END("==== END RENDER ===="); } diff --git a/engine/src/ext/gltf/gltf.cpp b/engine/src/ext/gltf/gltf.cpp index 592a9fb0..2ae1adbf 100644 --- a/engine/src/ext/gltf/gltf.cpp +++ b/engine/src/ext/gltf/gltf.cpp @@ -151,14 +151,14 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t { graph.images.reserve(model.images.size()); for ( auto& i : model.images ) { + size_t index = graph.images.size(); auto& image = graph.images.emplace_back(); image.loadFromBuffer( &i.image[0], {i.width, i.height}, 8, i.component, true ); } } // generate atlas - if ( mode & ext::gltf::LoadMode::ATLAS ) { if ( graph.atlas ) delete graph.atlas; graph.atlas = new uf::Atlas; - auto& atlas = *graph.atlas; - atlas.generate( graph.images ); + if ( mode & ext::gltf::LoadMode::ATLAS ) { + graph.atlas.generate( graph.images ); } // load textures { @@ -169,10 +169,11 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t texture.storage.index = t.source; texture.storage.sampler = t.sampler; - if ( graph.atlas ) { - auto& atlas = *graph.atlas; - auto atlasMin = atlas.mapUv( {0, 0}, t.source ); - auto atlasMax = atlas.mapUv( {1, 1}, t.source ); + if ( 0 <= t.source && graph.atlas.generated() ) { + size_t index = t.source; + const auto& hash = graph.images[index].getHash(); + auto atlasMin = graph.atlas.mapUv( {0, 0}, hash ); + auto atlasMax = graph.atlas.mapUv( {1, 1}, hash ); texture.storage.lerp = { atlasMin.x, @@ -184,6 +185,9 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t } } } + if ( graph.atlas.generated() ) { + graph.atlas.clear(false); + } // load materials { graph.materials.reserve(model.materials.size()); diff --git a/engine/src/ext/gltf/graph.cpp b/engine/src/ext/gltf/graph.cpp index 3c446f2c..488c4c07 100644 --- a/engine/src/ext/gltf/graph.cpp +++ b/engine/src/ext/gltf/graph.cpp @@ -155,17 +155,16 @@ void uf::graph::process( pod::Graph& graph ) { } #endif } - if ( graph.atlas ) { - for ( auto& texture : graph.textures ) { - ++texture.storage.index; - } - auto& image = *graph.images.emplace(graph.images.begin(), graph.atlas->getAtlas()); + if ( graph.metadata["flags"]["ATLAS"].as() && graph.atlas.generated() ) { + // for ( auto& texture : graph.textures ) if ( 0 <= texture.storage.index ) ++texture.storage.index; + + auto& image = *graph.images.emplace(graph.images.begin(), graph.atlas.getAtlas()); auto& texture = *graph.textures.emplace(graph.textures.begin()); texture.name = "atlas"; texture.bind = true; texture.storage.index = 0; texture.storage.sampler = 0; - texture.storage.remap = 0; + texture.storage.remap = -1; texture.storage.blend = 0; if ( graph.metadata["filter"].is() ) { @@ -188,12 +187,19 @@ void uf::graph::process( pod::Graph& graph ) { if ( 0 <= material.storage.indexLightmap ) ++material.storage.indexLightmap; } texture.texture.loadFromImage( image ); + + // remap texture slots + size_t textureSlot = 0; + for ( auto& texture : graph.textures ) { + texture.storage.index = -1; + if ( !texture.bind ) continue; + texture.storage.index = textureSlot++; + } } else { for ( size_t i = 0; i < graph.textures.size() && i < graph.images.size(); ++i ) { auto& image = graph.images[i]; auto& texture = graph.textures[i]; texture.bind = true; - texture.storage.index = i; if ( graph.metadata["filter"].is() ) { std::string filter = graph.metadata["filter"].as(); if ( filter == "NEAREST" ) { @@ -207,6 +213,7 @@ void uf::graph::process( pod::Graph& graph ) { texture.texture.loadFromImage( image ); } } +/* { size_t textureSlot = 0; for ( auto& texture : graph.textures ) { @@ -215,6 +222,7 @@ void uf::graph::process( pod::Graph& graph ) { texture.storage.index = textureSlot++; } } +*/ if ( !graph.root.entity ) graph.root.entity = new uf::Object; for ( auto index : graph.root.children ) process( graph, index, *graph.root.entity ); @@ -318,8 +326,22 @@ void uf::graph::process( pod::Graph& graph ) { if ( entity->hasComponent() ) { auto& graphic = entity->getComponent(); graphic.initialize(); - graphic.initializeMesh( mesh, 0 ); #if 1 + if ( entity->getName() == "worldspawn_20" && ext::json::isObject( graph.metadata["grid"] ) ) { + auto sliced = mesh; + auto& grid = entity->getComponent(); + grid.initialize( sliced, uf::vector::decode( graph.metadata["grid"]["size"], pod::Vector3ui{1,1,1} ) ); + grid.analyze(); + + auto center = uf::vector::decode( graph.metadata["grid"]["center"], grid.center() ); + sliced.indices = grid.get<>( center ); + graphic.initializeMesh( sliced ); + } else { + graphic.initializeMesh( mesh ); + } + #else + graphic.initialize(); + graphic.initializeMesh( mesh, 0 ); if ( ext::json::isObject( graph.metadata["grid"] ) ) { auto& grid = entity->getComponent(); grid.initialize( mesh, uf::vector::decode( graph.metadata["grid"]["size"], pod::Vector3ui{1,1,1} ) ); @@ -442,7 +464,10 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) if ( graph.metadata["lightmapped"].as() && !(metadataLight["shadows"].as() || metadataLight["dynamic"].as()) ) continue; auto& metadataJson = entity.getComponent(); entity.load("/light.json"); - metadataJson["light"] = metadataLight; + // copy + ext::json::forEach( metadataLight, [&]( const std::string& key, ext::json::Value& value ) { + metadataJson["light"][key] = value; + }); break; } } @@ -490,14 +515,6 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) // preprocess mesh for ( auto& vertex : nodeMesh.vertices ) { vertex.id.x = node.index; - // in almost-software mode, material ID is actually its albedo ID, as we can't use any other forms of mapping - #if UF_USE_OPENGL_FIXED_FUNCTION - if ( !(graph.metadata["flags"]["ATLAS"].as()) ) { - auto& material = graph.materials[vertex.id.y]; - auto& texture = graph.textures[material.storage.indexAlbedo]; - vertex.id.y = texture.storage.index; - } - #endif } auto& mesh = entity.getComponent(); @@ -548,9 +565,7 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) void uf::graph::cleanup( pod::Graph& graph ) { graph.images.clear(); graph.meshes.clear(); - if ( graph.atlas ) { - graph.atlas->getAtlas().clear(); - } + graph.atlas.clear(); } void uf::graph::override( pod::Graph& graph ) { graph.settings.animations.override.a = 0; @@ -691,7 +706,6 @@ void uf::graph::destroy( pod::Graph& graph ) { for ( auto& t : graph.textures ) { t.texture.destroy(); } - delete graph.atlas; } #include @@ -905,6 +919,18 @@ pod::Graph uf::graph::load( const std::string& filename, ext::gltf::load_mode_t return 0; }); jobs.emplace_back([&]{ + if ( !ext::json::isNull( serializer["atlas"] ) ) { + UF_DEBUG_TRACE_MSG("Reading atlas..."); + auto& image = graph.atlas.getAtlas(); + auto& value = serializer["atlas"]; + if ( value.is() ) { + std::string filename = directory + "/" + value.as(); + UF_DEBUG_TRACE_MSG("Reading atlas " << filename); + image.open(filename, false); + } else { + decode( value, image ); + } + } // load images UF_DEBUG_TRACE_MSG("Reading images..."); graph.images.reserve( serializer["images"].size() ); @@ -1010,6 +1036,18 @@ pod::Graph uf::graph::load( const std::string& filename, ext::gltf::load_mode_t } }); // load images + if ( !ext::json::isNull( serializer["atlas"] ) ) { + UF_DEBUG_TRACE_MSG("Reading atlas..."); + auto& image = graph.atlas.getAtlas(); + auto& value = serializer["atlas"]; + if ( value.is() ) { + std::string filename = directory + "/" + value.as(); + UF_DEBUG_TRACE_MSG("Reading atlas " << filename); + image.open(filename, false); + } else { + decode( value, image ); + } + } UF_DEBUG_TRACE_MSG("Reading images..."); graph.images.reserve( serializer["images"].size() ); ext::json::forEach( serializer["images"], [&]( ext::json::Value& value ){ @@ -1074,12 +1112,14 @@ pod::Graph uf::graph::load( const std::string& filename, ext::gltf::load_mode_t }); decode(serializer["root"], graph.root); #endif +#if 0 // generate atlas - if ( graph.metadata["flags"]["ATLAS"].as() ) { if ( graph.atlas ) delete graph.atlas; graph.atlas = new uf::Atlas; + if ( graph.metadata["flags"]["ATLAS"].as() ) { UF_DEBUG_TRACE_MSG("Generating atlas..."); - auto& atlas = *graph.atlas; - atlas.generate( graph.images ); + graph.atlas.generate( graph.images ); + graph.atlas.clear(false); } +#endif // re-reference all transform parents for ( auto& node : graph.nodes ) { if ( 0 <= node.parent && node.parent < graph.nodes.size() && node.index != node.parent ) { @@ -1244,6 +1284,17 @@ void uf::graph::save( const pod::Graph& graph, const std::string& filename ) { #if UF_GRAPH_LOAD_MULTITHREAD std::vector> jobs; jobs.emplace_back([&]{ + if ( graph.atlas.generated() ) { + auto& image = graph.atlas.getAtlas(); + if ( saveSeparately ) { + std::string f = "atlas"; + f += compression?".jpg":".png"; + image.save(directory + "/" + f); + serializer["atlas"] = f; + } else { + serializer["atlas"] = encode(image, compression); + } + } ext::json::reserve( serializer["images"], graph.images.size() ); if ( saveSeparately ) { for ( size_t i = 0; i < graph.images.size(); ++i ) { @@ -1323,6 +1374,16 @@ void uf::graph::save( const pod::Graph& graph, const std::string& filename ) { }); if ( !jobs.empty() ) uf::thread::batchWorkers( jobs ); #else + if ( graph.atlas.generated() ) { + auto& image = graph.atlas.getAtlas(); + if ( saveSeparately ) { + std::string f = "atlas"+(compression?".jpg":".png"); + image.save(directory + "/" + f); + serializer["atlas"] = f; + } else { + serializer["atlas"] = encode(image, compression); + } + } ext::json::reserve( serializer["images"], graph.images.size() ); if ( saveSeparately ) { for ( size_t i = 0; i < graph.images.size(); ++i ) { diff --git a/engine/src/ext/lua/lua.cpp b/engine/src/ext/lua/lua.cpp index fe417d68..7ae79dbb 100644 --- a/engine/src/ext/lua/lua.cpp +++ b/engine/src/ext/lua/lua.cpp @@ -55,6 +55,112 @@ void ext::lua::onInitialization( const std::function& function ) { functions.emplace_back(function); } + +namespace binds { + namespace hook { + void add( const std::string& name, const sol::function& function ) { + uf::hooks.addHook( name, [function](ext::json::Value& json){ + sol::table table = ext::lua::state["json"]["decode"]( json.dump() ); + auto result = function( table ); + if ( !result.valid() ) { + sol::error err = result; + uf::iostream << err.what() << "\n"; + } + }); + }; + void call( const std::string& name, sol::table table = ext::lua::createTable() ) { + uf::Serializer payload = table; + uf::hooks.call( name, (ext::json::Value&) payload ); + return; + }; + } + namespace entities { + uf::Object& get(const uint& uid) { + auto* p = uf::Entity::globalFindByUid(uid); + if ( p ) return p->as(); + static uf::Object null; + return null; + }; + uf::Object& currentScene() { + return uf::scene::getCurrentScene().as(); + }; + uf::Object& controller(){ + return uf::scene::getCurrentScene().getController().as(); + }; + void destroy( uf::Object& object ) { + object.getParent().removeChild(object); + object.destroy(); + // delete &object; + }; + } + namespace string { + std::string extension( const std::string& filename ) { + return uf::io::extension( filename ); + }; + std::string resolveURI( const std::string& filename, sol::variadic_args va ) { + auto it = va.begin(); + std::string root = it != va.end() ? *(it++) : std::string(""); + return uf::io::resolveURI( filename, root ); + }; + std::string si( sol::variadic_args va ) { + auto it = va.begin(); + double value = *(it++); + std::string unit = *(it++); + size_t precision = va.size() > 2 ? *(it++) : 3; + return uf::string::si( value, unit, precision ); + }; + } + namespace io { + void print( sol::variadic_args va ) { + size_t count = va.size(); + for ( auto value : va ) { + std::string str = ext::lua::state["tostring"]( value ); + uf::iostream << str; + if ( --count != 0 ) uf::iostream << "\t"; + } + uf::iostream << "\n"; + }; + } + namespace math { + double clamp( double value, double min, double max ) { + return std::clamp( value, min, max ); + }; + } + namespace time { + double current(){ return uf::physics::time::current; }; + double previous(){ return uf::physics::time::previous; }; + double delta(){ return uf::physics::time::delta; }; + } + namespace json { + std::string pretty( const std::string& json ){ + uf::Serializer serializer = json; + return serializer.serialize(); + }; + sol::table readFromFile( const std::string& filename ){ + uf::Serializer serializer; + serializer.readFromFile( filename ); + std::string string = serializer.serialize(false); + auto decoded = ext::lua::decode( string ); + return decoded ? decoded.value() : ext::lua::createTable(); + }; + bool writeToFile( sol::table table, const std::string& path ) { + if ( uf::io::extension(path) != "json" ) return false; + auto encoded = ext::lua::encode( table ); + if ( encoded ) { + uf::Serializer json = encoded.value(); + json.writeToFile( path ); + return true; + } + return false; + }; + } + namespace os { + std::string arch() { + return UF_ENV; + } + } +} + void ext::lua::initialize() { state.open_libraries(sol::lib::base, sol::lib::package, sol::lib::table, sol::lib::math, sol::lib::string, sol::lib::ffi, sol::lib::jit); @@ -79,118 +185,56 @@ void ext::lua::initialize() { { auto hooks = state["hooks"].get_or_create(); - hooks["add"] = []( const std::string& name, const sol::function& function ) { - uf::hooks.addHook( name, [function](ext::json::Value& json){ - sol::table table = ext::lua::state["json"]["decode"]( json.dump() ); - auto result = function( table ); - if ( !result.valid() ) { - sol::error err = result; - uf::iostream << err.what() << "\n"; - } - }); - }; - hooks["call"] = []( const std::string& name, sol::table table = createTable() ) { - uf::Serializer payload = table; - return uf::hooks.call( name, (ext::json::Value&) payload ); - }; + hooks["add"] = UF_LUA_C_FUN(::binds::hook::add); + hooks["call"] = UF_LUA_C_FUN(::binds::hook::call); } // `entities` table { auto entities = state["entities"].get_or_create(); - entities["get"] = [](const uint& uid)->uf::Object&{ - auto* p = uf::Entity::globalFindByUid(uid); - if ( p ) return p->as(); - static uf::Object null; - return null; - }; - entities["currentScene"] = []()->uf::Object&{ - return uf::scene::getCurrentScene().as(); - }; - entities["controller"] = []()->uf::Object&{ - return uf::scene::getCurrentScene().getController().as(); - }; - entities["destroy"] = []( uf::Object& object ){ - object.getParent().removeChild(object); - object.destroy(); - // delete &object; - }; + entities["get"] = UF_LUA_C_FUN(::binds::entities::get); + entities["currentScene"] = UF_LUA_C_FUN(::binds::entities::currentScene); + entities["controller"] = UF_LUA_C_FUN(::binds::entities::controller); + entities["destroy"] = UF_LUA_C_FUN(::binds::entities::destroy); } // `string` table { auto string = state["string"].get_or_create(); - string["extension"] = []( const std::string& filename ) { - return uf::io::extension( filename ); - }; - string["resolveURI"] = []( const std::string& filename, sol::variadic_args va ) { - auto it = va.begin(); - std::string root = it != va.end() ? *(it++) : std::string(""); - return uf::io::resolveURI( filename, root ); - }; - string["si"] = []( sol::variadic_args va ) { - auto it = va.begin(); - double value = *(it++); - std::string unit = *(it++); - size_t precision = va.size() > 2 ? *(it++) : 3; - return uf::string::si( value, unit, precision ); - }; + string["extension"] = UF_LUA_C_FUN(::binds::string::extension); + string["resolveURI"] = UF_LUA_C_FUN(::binds::string::resolveURI); + string["si"] = UF_LUA_C_FUN(::binds::string::si); } // `io` table { auto io = state["io"].get_or_create(); - io["print"] = []( sol::variadic_args va ) { - size_t count = va.size(); - for ( auto value : va ) { - std::string str = ext::lua::state["tostring"]( value ); - uf::iostream << str; - if ( --count != 0 ) uf::iostream << "\t"; - } - uf::iostream << "\n"; - }; + io["print"] = UF_LUA_C_FUN(::binds::io::print); } // `math` table { auto math = state["math"].get_or_create(); - math["clamp"] = []( double value, double min, double max ) { - return std::clamp( value, min, max ); - }; + math["clamp"] = UF_LUA_C_FUN(::binds::math::clamp); } // `time` table { auto time = state["time"].get_or_create(); - time["current"] = []()->double{ return uf::physics::time::current; }; - time["previous"] = []()->double{ return uf::physics::time::previous; }; - time["delta"] = []()->double{ return uf::physics::time::delta; }; + time.set("current", UF_LUA_C_FUN(::binds::time::current)); + time.set("previous", UF_LUA_C_FUN(::binds::time::previous)); + time.set("delta", UF_LUA_C_FUN(::binds::time::delta)); } // `json` table { - state["json"]["pretty"] = []( const std::string& json )->std::string{ - uf::Serializer serializer = json; - return serializer.serialize(); - }; - state["json"]["readFromFile"] = []( const std::string& filename ){ - uf::Serializer serializer; - serializer.readFromFile( filename ); - std::string string = serializer.serialize(false); - auto decoded = decode( string ); - return decoded ? decoded.value() : ext::lua::createTable(); - }; - state["json"]["writeToFile"] = []( sol::table table, const std::string& path ) { - if ( uf::io::extension(path) != "json" ) return false; - auto encoded = encode( table ); - if ( encoded ) { - uf::Serializer json = encoded.value(); - json.writeToFile( path ); - return true; - } - return false; - }; + state["json"]["pretty"] = UF_LUA_C_FUN(::binds::json::pretty); + state["json"]["readFromFile"] = UF_LUA_C_FUN(::binds::json::readFromFile); + state["json"]["writeToFile"] = UF_LUA_C_FUN(::binds::json::writeToFile); } // `window` table { auto window = state["window"].get_or_create(); - window["keyPressed"] = [](const std::string& name)->bool{ - return uf::Window::isKeyPressed(name); - }; + window["keyPressed"] = UF_LUA_C_FUN(uf::Window::isKeyPressed); + } + // `os` table + { + auto os = state["os"].get_or_create(); + os["arch"] = UF_LUA_C_FUN(::binds::os::arch); } run(main); } diff --git a/engine/src/ext/lua/usertypes/asset.cpp b/engine/src/ext/lua/usertypes/asset.cpp index 82c46613..3c695edf 100644 --- a/engine/src/ext/lua/usertypes/asset.cpp +++ b/engine/src/ext/lua/usertypes/asset.cpp @@ -1,8 +1,9 @@ #include #if UF_USE_LUA #include -UF_LUA_REGISTER_USERTYPE(uf::Asset, - UF_LUA_REGISTER_USERTYPE_DEFINE( load, []( uf::Asset& asset, sol::variadic_args va ) { + +namespace binds { + void load( uf::Asset& asset, sol::variadic_args va ) { auto it = va.begin(); std::string callback = ""; std::string uri = ""; @@ -12,12 +13,10 @@ UF_LUA_REGISTER_USERTYPE(uf::Asset, 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 ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( cache, []( uf::Asset& asset, sol::variadic_args va ) { + if ( callback == "" ) asset.load( uri, hash, category ); + else asset.load( callback, uri, hash, category ); + } + void cache( uf::Asset& asset, sol::variadic_args va ) { auto it = va.begin(); std::string callback = ""; std::string uri = ""; @@ -31,7 +30,15 @@ UF_LUA_REGISTER_USERTYPE(uf::Asset, asset.cache( uri, hash, category ); else asset.cache( callback, uri, hash, category ); - }), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Asset::getOriginal ) -) + } + std::string getOriginal( uf::Asset& asset, const std::string& n ) { + return asset.getOriginal( n ); + } +} + +UF_LUA_REGISTER_USERTYPE(uf::Asset, + UF_LUA_REGISTER_USERTYPE_DEFINE( load, UF_LUA_C_FUN(::binds::load) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( cache, UF_LUA_C_FUN(::binds::cache) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( getOriginal, UF_LUA_C_FUN(::binds::getOriginal) ) + ) #endif \ No newline at end of file diff --git a/engine/src/ext/lua/usertypes/audio.cpp b/engine/src/ext/lua/usertypes/audio.cpp index 1e016785..87f595fe 100644 --- a/engine/src/ext/lua/usertypes/audio.cpp +++ b/engine/src/ext/lua/usertypes/audio.cpp @@ -7,27 +7,27 @@ UF_LUA_REGISTER_USERTYPE(uf::Audio, if ( filename != "" ) self.load(filename); self.setVolume(volume); }), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::initialized ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::playing ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::destroy ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::load ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::play ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::stop ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::getTime ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::setTime ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::getDuration ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::setPosition ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::setOrientation ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::setVolume ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::getPitch ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::setPitch ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::getGain ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::setGain ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::getRolloffFactor ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::setRolloffFactor ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::getMaxDistance ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::setMaxDistance ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::getVolume ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Audio::getFilename ) + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::initialized ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::playing ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::destroy ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::load ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::play ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::stop ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::getTime ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::setTime ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::getDuration ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::setPosition ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::setOrientation ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::setVolume ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::getPitch ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::setPitch ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::getGain ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::setGain ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::getRolloffFactor ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::setRolloffFactor ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::getMaxDistance ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::setMaxDistance ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::getVolume ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Audio::getFilename ) ) #endif \ No newline at end of file diff --git a/engine/src/ext/lua/usertypes/camera.cpp b/engine/src/ext/lua/usertypes/camera.cpp index a8f3beb6..e7bbe678 100644 --- a/engine/src/ext/lua/usertypes/camera.cpp +++ b/engine/src/ext/lua/usertypes/camera.cpp @@ -1,42 +1,56 @@ #include #if UF_USE_LUA #include -UF_LUA_REGISTER_USERTYPE(uf::Camera, - UF_LUA_REGISTER_USERTYPE_DEFINE( getTransform, []( uf::Camera& self ) { + +namespace binds { + pod::Transform<>& getTransform( uf::Camera& self ) { return self.getTransform(); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( getView, []( const uf::Camera& self, sol::variadic_args va ) { + } + pod::Matrix4f getView( const uf::Camera& self, sol::variadic_args va ) { auto it = va.begin(); if ( va.size() > 0 ) { size_t i = *it++; return self.getView(i); } return self.getView(); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( getProjection, []( const uf::Camera& self, sol::variadic_args va ) { + } + pod::Matrix4f getProjection( const uf::Camera& self, sol::variadic_args va ) { auto it = va.begin(); if ( va.size() > 0 ) { size_t i = *it++; return self.getProjection(i); } return self.getProjection(); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( setView, []( uf::Camera& self, const pod::Matrix4f& matrix, sol::variadic_args va ) { + } + void setView( uf::Camera& self, const pod::Matrix4f& matrix, sol::variadic_args va ) { auto it = va.begin(); if ( va.size() > 0 ) { size_t i = *it++; - return self.setView(matrix, i); + self.setView(matrix, i); + } else { + self.setView(matrix); } - return self.setView(matrix); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( setProjection, []( uf::Camera& self, const pod::Matrix4f& matrix, sol::variadic_args va ) { + } + void setProjection( uf::Camera& self, const pod::Matrix4f& matrix, sol::variadic_args va ) { auto it = va.begin(); if ( va.size() > 0 ) { size_t i = *it++; - return self.setProjection(matrix, i); + self.setProjection(matrix, i); + } else { + self.setProjection(matrix); } - return self.setProjection(matrix); - }), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Camera::update ) + } + void update( uf::Camera& self, bool force = true ) { + self.update(force); + } +} + +UF_LUA_REGISTER_USERTYPE(uf::Camera, + UF_LUA_REGISTER_USERTYPE_DEFINE( getTransform, UF_LUA_C_FUN(::binds::getTransform) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( getView, UF_LUA_C_FUN(::binds::getView) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( setView, UF_LUA_C_FUN(::binds::setView) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( getProjection, UF_LUA_C_FUN(::binds::getProjection) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( setProjection, UF_LUA_C_FUN(::binds::setProjection) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( update, UF_LUA_C_FUN(::binds::update) ) ) #endif \ No newline at end of file diff --git a/engine/src/ext/lua/usertypes/matrix.cpp b/engine/src/ext/lua/usertypes/matrix.cpp index 8fd200d1..eea621e2 100644 --- a/engine/src/ext/lua/usertypes/matrix.cpp +++ b/engine/src/ext/lua/usertypes/matrix.cpp @@ -2,6 +2,27 @@ #if UF_USE_LUA #include +namespace binds { + float index( const pod::Matrix4f& self, const size_t& index ) { + return self[index]; + } + pod::Matrix4f translate( const pod::Vector3f& v ) { + return uf::matrix::translate( uf::matrix::identity(), v ); + } + pod::Matrix4f scale( const pod::Vector3f& v ) { + return uf::matrix::scale( uf::matrix::identity(), v ); + } + pod::Matrix4f multiply( const pod::Matrix4f& left, const pod::Matrix4f& right ) { + return uf::matrix::multiply( left, right ); + } + pod::Matrix4f inverse( const pod::Matrix4f& m ) { + return uf::matrix::inverse( m ); + } + pod::Matrix4f identity( const pod::Matrix4f& ) { + return uf::matrix::identity(); + } +} + UF_LUA_REGISTER_USERTYPE(pod::Matrix4f, sol::call_constructor, sol::initializers( []( pod::Matrix4f& self ) { @@ -11,26 +32,12 @@ UF_LUA_REGISTER_USERTYPE(pod::Matrix4f, return self = copy; } ), - sol::meta_function::multiplication, []( const pod::Matrix4f& left, const pod::Matrix4f& right ) { - return uf::matrix::multiply( left, right ); - }, - UF_LUA_REGISTER_USERTYPE_DEFINE( m, []( pod::Matrix4f& self, const size_t& index ) { - return self[index]; - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( multiply, []( const pod::Matrix4f& left, const pod::Matrix4f& right ) { - return uf::matrix::multiply( left, right ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( inverse, []( const pod::Matrix4f& m ) { - return uf::matrix::inverse( m ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( translate, []( const pod::Vector3f& v ) { - return uf::matrix::translate( uf::matrix::identity(), v ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( scale, []( const pod::Vector3f& v ) { - return uf::matrix::scale( uf::matrix::identity(), v ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( identity, []( ) { - return uf::matrix::identity(); - }) + sol::meta_function::multiplication, UF_LUA_C_FUN( ::binds::multiply ), + UF_LUA_REGISTER_USERTYPE_DEFINE( m, UF_LUA_C_FUN( ::binds::index ) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( multiply, UF_LUA_C_FUN( ::binds::multiply ) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( inverse, UF_LUA_C_FUN( ::binds::inverse ) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( translate, UF_LUA_C_FUN( ::binds::translate ) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( scale, UF_LUA_C_FUN( ::binds::scale ) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( identity, UF_LUA_C_FUN(uf::matrix::identity) ) ) #endif \ No newline at end of file diff --git a/engine/src/ext/lua/usertypes/object.cpp b/engine/src/ext/lua/usertypes/object.cpp index 0762b561..70fec7c7 100644 --- a/engine/src/ext/lua/usertypes/object.cpp +++ b/engine/src/ext/lua/usertypes/object.cpp @@ -7,6 +7,177 @@ #include #include +namespace binds { + std::string formatHookName(uf::Object& self, const std::string n ){ + return self.formatHookName(n); + } + sol::object getComponent( uf::Object& self, const std::string& type ) { + #define UF_LUA_RETRIEVE_COMPONENT( T )\ + else if ( type == UF_NS_GET_LAST(T) ) return sol::make_object( ext::lua::state, std::ref(self.getComponent()) ); + + if ( type == "Metadata" ) { + auto& metadata = self.getComponent(); + auto decoded = ext::lua::decode( metadata ); + if ( decoded ) { + sol::table table = decoded.value(); + return sol::make_object( ext::lua::state, table ); + } + } + UF_LUA_RETRIEVE_COMPONENT(pod::Transform<>) + UF_LUA_RETRIEVE_COMPONENT(uf::Audio) + UF_LUA_RETRIEVE_COMPONENT(uf::Asset) + UF_LUA_RETRIEVE_COMPONENT(uf::Camera) + return sol::make_object( ext::lua::state, sol::lua_nil ); + } + void setComponent(uf::Object& self, const std::string& type, sol::object value ) { + #define UF_LUA_UPDATE_COMPONENT( T )\ + else if ( type == UF_NS_GET_LAST(T) ) self.getComponent() = std::move(value.as()); + + if ( type == "Metadata" ) { + auto encoded = ext::lua::encode( value.as() ); + if ( encoded ) { + auto& metadata = self.getComponent(); + std::string str = encoded.value(); + uf::Serializer hooks = metadata["system"]["hooks"]; + metadata.merge( str, false ); + metadata["system"]["hooks"] = hooks; + } + } + UF_LUA_UPDATE_COMPONENT(pod::Transform<>) + UF_LUA_UPDATE_COMPONENT(uf::Audio) + UF_LUA_UPDATE_COMPONENT(uf::Asset) + UF_LUA_UPDATE_COMPONENT(uf::Camera) + } + bool bind(uf::Object& self, const std::string& type, sol::protected_function fun ) { + if ( !self.hasBehavior({.type = uf::LuaBehavior::type}) ) uf::instantiator::bind( "LuaBehavior", self ); + pod::Behavior* behaviorPointer = NULL; + auto& behaviors = self.getBehaviors(); + for ( auto& b : behaviors ) { + if ( b.type != uf::LuaBehavior::type ) continue; + behaviorPointer = &b; + break; + } + if ( !behaviorPointer ) return false; + pod::Behavior& behavior = *behaviorPointer; + + pod::Behavior::function_t* functionPointer = NULL; + if ( type == "initialize" ) functionPointer = &behavior.initialize; + else if ( type == "tick" ) functionPointer = &behavior.tick; + else if ( type == "render" ) functionPointer = &behavior.render; + else if ( type == "destroy" ) functionPointer = &behavior.destroy; + + if ( !functionPointer ) return false; + pod::Behavior::function_t& function = *functionPointer; + + function = [fun]( uf::Object& s ) { + auto result = fun(s); + if ( !result.valid() ) { + sol::error err = result; + uf::iostream << err.what() << "\n"; + } + }; + return true; + } + uf::Object& findByUid( uf::Object& self, const size_t& index ) { + auto* pointer = self.findByUid( index ); + if ( pointer ) return pointer->as(); + static uf::Object null; + return null; + } + uf::Object& findByName( uf::Object& self, const std::string& index ){ + auto* pointer = self.findByName( index ); + if ( pointer ) return pointer->as(); + static uf::Object null; + return null; + } + uf::Object& addChild( uf::Object& self, uf::Object& child ) { + self.addChild( child ); + return self; + } + uf::Object& removeChild( uf::Object& self, uf::Object& child ){ + self.removeChild( child ); + return self; + } + uf::Object& loadChild( uf::Object& self, const std::string& filename, bool init = true ) { + auto* pointer = self.loadChildPointer( filename, init ); + if ( pointer ) return pointer->as(); + static uf::Object null; + return null; + } + sol::table getChildren( uf::Object& self ){ + sol::table table = ext::lua::createTable(); + for ( auto* child : self.getChildren() ) { + table.add(&child->as()); + } + return table; + } + uf::Object& getParent( uf::Object& self ){ + return self.getParent().as(); + } + void addHook( uf::Object& self, const std::string& name, const sol::function& function ) { + self.addHook( name, [function](ext::json::Value& json){ + std::string payload = json.dump(); + auto decoded = ext::lua::decode( payload ); + if ( !decoded ) return; + sol::table table = decoded.value(); + auto result = function( table ); + if ( !result.valid() ) { + sol::error err = result; + uf::iostream << err.what() << "\n"; + return; + } + }); + } + void callHook( uf::Object& self, const std::string& name, sol::table table = ext::lua::createTable() ) { + uf::Serializer payload = table; + self.callHook( name, (ext::json::Value&) payload ); + } + void queueHook( uf::Object& self, const std::string& name, sol::table table, float delay = 0.0f ) { + uf::Serializer payload = table; + self.queueHook( name, (ext::json::Value&) payload, delay ); + } + std::string toString( uf::Object& self ) { + return self.getName() + ": " + std::to_string( self.getUid() ); + } + + size_t getUid( const uf::Object& o ) { return o.getUid(); } + std::string getName( const uf::Object& o ) { return o.getName(); } +} + +UF_LUA_REGISTER_USERTYPE(uf::Object, + sol::call_constructor, sol::initializers( + []( uf::Object& self, sol::object arg, bool init = true ){ + if ( arg.is() ) { + self.load( arg.as() ); + } else if ( arg.is() ) { + auto encoded = ext::lua::encode( arg.as() ); + if ( encoded ) { + uf::Serializer json = encoded.value(); + self.load(json); + } + } + if ( init ) self.initialize(); + } + ), + UF_LUA_REGISTER_USERTYPE_DEFINE( uid, UF_LUA_C_FUN(::binds::getUid) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( name, UF_LUA_C_FUN(::binds::getName) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( formatHookName, UF_LUA_C_FUN(::binds::formatHookName) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( getComponent, UF_LUA_C_FUN(::binds::getComponent) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( setComponent, UF_LUA_C_FUN(::binds::setComponent) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( bind, UF_LUA_C_FUN(::binds::bind) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( findByUid, UF_LUA_C_FUN(::binds::findByUid) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( findByName, UF_LUA_C_FUN(::binds::findByName) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( addChild, UF_LUA_C_FUN(::binds::addChild) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( removeChild, UF_LUA_C_FUN(::binds::removeChild) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( loadChild, UF_LUA_C_FUN(::binds::loadChild) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( getChildren, UF_LUA_C_FUN(::binds::getChildren) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( getParent, UF_LUA_C_FUN(::binds::getParent) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( addHook, UF_LUA_C_FUN(::binds::addHook) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( callHook, UF_LUA_C_FUN(::binds::callHook) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( queueHook, UF_LUA_C_FUN(::binds::queueHook) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, UF_LUA_C_FUN(::binds::toString) ) +) +/* namespace { static uf::StaticInitialization TOKEN_PASTE(STATIC_INITIALIZATION_, __LINE__)( []{ ext::lua::onInitialization( []{ @@ -21,145 +192,28 @@ namespace { self.load(json); } } - if ( init ) { - self.initialize(); - } + if ( init ) self.initialize(); }), - "uid", &uf::Object::getUid , - "name", &uf::Object::getName , - "formatHookName", [](uf::Object& self, const std::string n ){ - return self.formatHookName(n); - }, - "getComponent", [](uf::Object& self, const std::string& type )->sol::object{ - #define UF_LUA_RETRIEVE_COMPONENT( T )\ - if ( type == UF_NS_GET_LAST(T) ) return sol::make_object( ext::lua::state, std::ref(self.getComponent()) ); - - if ( type == "Metadata" ) { - auto& metadata = self.getComponent(); - auto decoded = ext::lua::decode( metadata ); - if ( decoded ) { - sol::table table = decoded.value(); - return sol::make_object( ext::lua::state, table ); - } - } - UF_LUA_RETRIEVE_COMPONENT(pod::Transform<>) - UF_LUA_RETRIEVE_COMPONENT(uf::Audio) - UF_LUA_RETRIEVE_COMPONENT(uf::Asset) - UF_LUA_RETRIEVE_COMPONENT(uf::Camera) - return sol::make_object( ext::lua::state, sol::lua_nil ); - }, - "setComponent", [](uf::Object& self, const std::string& type, sol::object value ) { - #define UF_LUA_UPDATE_COMPONENT( T )\ - else if ( type == UF_NS_GET_LAST(T) ) self.getComponent() = std::move(value.as()); - - if ( type == "Metadata" ) { - auto encoded = ext::lua::encode( value.as() ); - if ( encoded ) { - auto& metadata = self.getComponent(); - std::string str = encoded.value(); - uf::Serializer hooks = metadata["system"]["hooks"]; - metadata.merge( str, false ); - metadata["system"]["hooks"] = hooks; - } - } - UF_LUA_UPDATE_COMPONENT(pod::Transform<>) - UF_LUA_UPDATE_COMPONENT(uf::Audio) - UF_LUA_UPDATE_COMPONENT(uf::Asset) - UF_LUA_UPDATE_COMPONENT(uf::Camera) - }, - "bind", [](uf::Object& self, const std::string& type, sol::protected_function fun ) { - if ( !self.hasBehavior({.type = uf::LuaBehavior::type}) ) uf::instantiator::bind( "LuaBehavior", self ); - pod::Behavior* behaviorPointer = NULL; - auto& behaviors = self.getBehaviors(); - for ( auto& b : behaviors ) { - if ( b.type != uf::LuaBehavior::type ) continue; - behaviorPointer = &b; - break; - } - if ( !behaviorPointer ) return false; - pod::Behavior& behavior = *behaviorPointer; - - pod::Behavior::function_t* functionPointer = NULL; - if ( type == "initialize" ) functionPointer = &behavior.initialize; - else if ( type == "tick" ) functionPointer = &behavior.tick; - else if ( type == "render" ) functionPointer = &behavior.render; - else if ( type == "destroy" ) functionPointer = &behavior.destroy; - - if ( !functionPointer ) return false; - pod::Behavior::function_t& function = *functionPointer; - - function = [fun]( uf::Object& s ) { - auto result = fun(s); - if ( !result.valid() ) { - sol::error err = result; - uf::iostream << err.what() << "\n"; - } - }; - return true; - }, - "findByUid", []( uf::Object& self, const size_t& index )->uf::Object&{ - auto* pointer = self.findByUid( index ); - if ( pointer ) return pointer->as(); - static uf::Object null; - return null; - }, - "findByName", []( uf::Object& self, const std::string& index )->uf::Object&{ - auto* pointer = self.findByName( index ); - if ( pointer ) return pointer->as(); - static uf::Object null; - return null; - }, - "addChild", []( uf::Object& self, uf::Object& child )->uf::Object&{ - self.addChild( child ); - return self; - }, - "removeChild", []( uf::Object& self, uf::Object& child )->uf::Object&{ - self.removeChild( child ); - return self; - }, - "loadChild", []( uf::Object& self, const std::string& filename, bool init = true )->uf::Object&{ - auto* pointer = self.loadChildPointer( filename, init ); - if ( pointer ) return pointer->as(); - static uf::Object null; - return null; - }, - "getChildren", []( uf::Object& self )->sol::table{ - sol::table table = ext::lua::createTable(); - for ( auto* child : self.getChildren() ) { - table.add(&child->as()); - } - return table; - }, - "getParent", []( uf::Object& self )->uf::Object&{ - return self.getParent().as(); - }, - "addHook", []( uf::Object& self, const std::string& name, const sol::function& function ) { - self.addHook( name, [function](ext::json::Value& json){ - std::string payload = json.dump(); - auto decoded = ext::lua::decode( payload ); - if ( !decoded ) return; - sol::table table = decoded.value(); - auto result = function( table ); - if ( !result.valid() ) { - sol::error err = result; - uf::iostream << err.what() << "\n"; - return; - } - }); - }, - "callHook", []( uf::Object& self, const std::string& name, sol::table table = ext::lua::createTable() ) { - uf::Serializer payload = table; - self.callHook( name, (ext::json::Value&) payload ); - }, - "queueHook", []( uf::Object& self, const std::string& name, sol::table table, float delay = 0.0f ) { - uf::Serializer payload = table; - self.queueHook( name, (ext::json::Value&) payload, delay ); - }, - "__tostring", []( uf::Object& self ) { - return self.getName() + ": " + std::to_string( self.getUid() ); - } + "uid", UF_LUA_C_FUN(::binds::getUid), + "name", UF_LUA_C_FUN(::binds::getName), + "formatHookName", UF_LUA_C_FUN(::binds::formatHookName), + "getComponent", UF_LUA_C_FUN(::binds::getComponent), + "setComponent", UF_LUA_C_FUN(::binds::setComponent), + "bind", UF_LUA_C_FUN(::binds::bind), + "findByUid", UF_LUA_C_FUN(::binds::findByUid), + "findByName", UF_LUA_C_FUN(::binds::findByName), + "addChild", UF_LUA_C_FUN(::binds::addChild), + "removeChild", UF_LUA_C_FUN(::binds::removeChild), + "loadChild", UF_LUA_C_FUN(::binds::loadChild), + "getChildren", UF_LUA_C_FUN(::binds::getChildren), + "getParent", UF_LUA_C_FUN(::binds::getParent), + "addHook", UF_LUA_C_FUN(::binds::addHook), + "callHook", UF_LUA_C_FUN(::binds::callHook), + "queueHook", UF_LUA_C_FUN(::binds::queueHook), + "__tostring", UF_LUA_C_FUN(::binds::toString) ); }); }); } +*/ #endif \ No newline at end of file diff --git a/engine/src/ext/lua/usertypes/quaternion.cpp b/engine/src/ext/lua/usertypes/quaternion.cpp index a29ea801..82a3b521 100644 --- a/engine/src/ext/lua/usertypes/quaternion.cpp +++ b/engine/src/ext/lua/usertypes/quaternion.cpp @@ -2,6 +2,60 @@ #if UF_USE_LUA #include +namespace binds { + float index( const pod::Quaternion<>& self, const size_t& index ) { + return self[index]; + } + pod::Quaternion<> lookAt( const pod::Vector3f& at, const pod::Vector3f& up ) { + return uf::quaternion::lookAt( at, up ); + } + pod::Quaternion<> normalize( const pod::Quaternion<>& self ) { + return uf::quaternion::normalize( self ); + } + pod::Quaternion<> multiply( const pod::Quaternion<>& left, const pod::Quaternion<>& right ) { + return uf::quaternion::multiply( left, right ); + } + pod::Quaternion<> axisAngle( sol::object arg, float angle ){ + if ( arg.is() ) { + return uf::quaternion::axisAngle( arg.as(), angle ); + } else if ( arg.is() ) { + sol::table table = arg.as(); + return uf::quaternion::axisAngle( pod::Vector3f{ table[0], table[1], table[2] }, angle ); + } + return pod::Quaternion<>{}; + } + pod::Vector3f rotate( const pod::Quaternion<>& left, const pod::Vector3f& right ) { + return uf::quaternion::rotate( left, right ); + } + pod::Quaternion<> eulerAngles( const pod::Quaternion<>& quaternion ) { + return uf::quaternion::eulerAngles( quaternion ); + } + pod::Quaternion<> conjugate( const pod::Quaternion<>& quaternion ) { + return uf::quaternion::conjugate( quaternion ); + } + pod::Quaternion<> inverse( const pod::Quaternion<>& quaternion ) { + return uf::quaternion::inverse( quaternion ); + } + float pitch( const pod::Quaternion<>& quaternion ) { + return uf::quaternion::pitch( quaternion ); + } + float yaw( const pod::Quaternion<>& quaternion ) { + return uf::quaternion::yaw( quaternion ); + } + float roll( const pod::Quaternion<>& quaternion ) { + return uf::quaternion::roll( quaternion ); + } + pod::Quaternion<> slerp( const pod::Quaternion<>& left, const pod::Quaternion<>& right, float a ) { + return uf::quaternion::slerp( left, right, a ); + } + pod::Matrix4f matrix( const pod::Quaternion<>& q ) { + return uf::quaternion::matrix( q ); + } + std::string __tostring( const pod::Quaternion<>& self ) { + return uf::string::toString( self ); + } +} + UF_LUA_REGISTER_USERTYPE(pod::Quaternion<>, sol::call_constructor, sol::initializers( []( pod::Quaternion<>& self ) { @@ -14,63 +68,27 @@ UF_LUA_REGISTER_USERTYPE(pod::Quaternion<>, return self = uf::vector::create(x, y, z, w); } ), + UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Quaternion<>::x), UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Quaternion<>::y), UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Quaternion<>::z), UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Quaternion<>::w), - UF_LUA_REGISTER_USERTYPE_DEFINE(v, []( pod::Quaternion<>& self, const size_t& index ) { - return self[index]; - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( lookAt, []( const pod::Vector3f& source, const pod::Vector3f& destination ) { - return uf::quaternion::lookAt( source, destination ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( normalize, []( const pod::Quaternion<>& self ) { - return uf::quaternion::normalize( self ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( multiply, []( const pod::Quaternion<>& left, const pod::Quaternion<>& right ) { - return uf::quaternion::multiply( left, right ); - }), - sol::meta_function::multiplication, []( const pod::Quaternion<>& left, const pod::Quaternion<>& right ) { - return uf::quaternion::multiply( left, right ); - }, - UF_LUA_REGISTER_USERTYPE_DEFINE(axisAngle, []( sol::object arg, float angle ){ - if ( arg.is() ) { - return uf::quaternion::axisAngle( arg.as(), angle ); - } else if ( arg.is() ) { - sol::table table = arg.as(); - return uf::quaternion::axisAngle( pod::Vector3f{ table[0], table[1], table[2] }, angle ); - } - return pod::Quaternion<>{}; - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( rotate, []( const pod::Quaternion<>& left, const pod::Vector3f& right ) { - return uf::quaternion::rotate( left, right ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( eulerAngles, []( const pod::Quaternion<>& quaternion ) { - return uf::quaternion::eulerAngles( quaternion ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( conjugate, []( const pod::Quaternion<>& quaternion ) { - return uf::quaternion::conjugate( quaternion ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( inverse, []( const pod::Quaternion<>& quaternion ) { - return uf::quaternion::inverse( quaternion ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( pitch, []( const pod::Quaternion<>& quaternion ) { - return uf::quaternion::pitch( quaternion ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( yaw, []( const pod::Quaternion<>& quaternion ) { - return uf::quaternion::yaw( quaternion ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( roll, []( const pod::Quaternion<>& quaternion ) { - return uf::quaternion::roll( quaternion ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( slerp, []( const pod::Quaternion<>& left, const pod::Quaternion<>& right, float a ) { - return uf::quaternion::slerp( left, right, a ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( matrix, []( const pod::Quaternion<>& q ) { - return uf::quaternion::matrix( q ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, []( const pod::Quaternion<>& self ) { - return uf::string::toString( self ); - }) + + UF_LUA_REGISTER_USERTYPE_DEFINE( v, UF_LUA_C_FUN(::binds::index) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( lookAt, UF_LUA_C_FUN(::binds::lookAt) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( normalize, UF_LUA_C_FUN(::binds::normalize) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( multiply, UF_LUA_C_FUN(::binds::multiply) ), + sol::meta_function::multiplication, UF_LUA_C_FUN(::binds::multiply), + UF_LUA_REGISTER_USERTYPE_DEFINE(axisAngle, UF_LUA_C_FUN(::binds::axisAngle) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( rotate, UF_LUA_C_FUN( ::binds::rotate ) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( eulerAngles, UF_LUA_C_FUN( ::binds::eulerAngles ) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( conjugate, UF_LUA_C_FUN( ::binds::conjugate ) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( inverse, UF_LUA_C_FUN( ::binds::inverse ) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( pitch, UF_LUA_C_FUN( ::binds::pitch ) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( yaw, UF_LUA_C_FUN( ::binds::yaw ) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( roll, UF_LUA_C_FUN( ::binds::roll ) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( slerp, UF_LUA_C_FUN( ::binds::slerp ) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( matrix, UF_LUA_C_FUN( ::binds::matrix ) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, UF_LUA_C_FUN( ::binds::__tostring ) ) ) #endif \ No newline at end of file diff --git a/engine/src/ext/lua/usertypes/timer.cpp b/engine/src/ext/lua/usertypes/timer.cpp index f0fc87b2..94283e26 100644 --- a/engine/src/ext/lua/usertypes/timer.cpp +++ b/engine/src/ext/lua/usertypes/timer.cpp @@ -2,14 +2,21 @@ #if UF_USE_LUA #include +namespace binds { + double elapsed( uf::Timer<>& self ) { return self.elapsed().asDouble(); } + void start( uf::Timer<>& self ) { return self.start(); } + void stop( uf::Timer<>& self ) { return self.stop(); } + void reset( uf::Timer<>& self ) { return self.reset(); } + void update( uf::Timer<>& self ) { return self.update(); } + bool running( uf::Timer<>& self ) { return self.running(); } +} + UF_LUA_REGISTER_USERTYPE(uf::Timer<>, - UF_LUA_REGISTER_USERTYPE_DEFINE( elapsed, []( uf::Timer<>& self ) { - return self.elapsed().asDouble(); - }), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Timer<>::start ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Timer<>::stop ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Timer<>::reset ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Timer<>::update ), - UF_LUA_REGISTER_USERTYPE_MEMBER( uf::Timer<>::running ) + UF_LUA_REGISTER_USERTYPE_DEFINE( elapsed, UF_LUA_C_FUN(::binds::elapsed) ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Timer<>::start ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Timer<>::stop ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Timer<>::reset ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Timer<>::update ), + UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Timer<>::running ) ) #endif \ No newline at end of file diff --git a/engine/src/ext/lua/usertypes/transform.cpp b/engine/src/ext/lua/usertypes/transform.cpp index 118d5b94..4b7bb66b 100644 --- a/engine/src/ext/lua/usertypes/transform.cpp +++ b/engine/src/ext/lua/usertypes/transform.cpp @@ -2,15 +2,8 @@ #if UF_USE_LUA #include -UF_LUA_REGISTER_USERTYPE(pod::Transform<>, - UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::position), - UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::scale), - UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::up), - UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::right), - UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::forward), - UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::orientation), - UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::model), - UF_LUA_REGISTER_USERTYPE_DEFINE(move, []( pod::Transform<>& self, sol::variadic_args va ) { +namespace binds { + void move( pod::Transform<>& self, sol::variadic_args va ) { auto it = va.begin(); if ( va.size() == 1 ) { pod::Vector3f delta = *it++; @@ -20,8 +13,8 @@ UF_LUA_REGISTER_USERTYPE(pod::Transform<>, double delta = *it++; self = uf::transform::move( self, axis, delta ); } - }), - UF_LUA_REGISTER_USERTYPE_DEFINE(rotate, []( pod::Transform<>& self, sol::variadic_args va ) { + } + void rotate( pod::Transform<>& self, sol::variadic_args va ) { auto it = va.begin(); if ( va.size() == 1 ) { pod::Quaternion<> delta = *it++; @@ -31,22 +24,40 @@ UF_LUA_REGISTER_USERTYPE(pod::Transform<>, double delta = *it++; self = uf::transform::rotate( self, axis, delta ); } - }), - UF_LUA_REGISTER_USERTYPE_DEFINE(flatten, []( const pod::Transform<>& t ) { - return uf::transform::flatten(t); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE(reorient, []( const pod::Transform<>& t ) { + } + pod::Transform<> flatten( const pod::Transform<>& t ) { + return uf::transform::flatten( t ); + } + pod::Transform<> reorient( const pod::Transform<>& t ) { return uf::transform::reorient( t ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE(getReference, []( pod::Transform<>& t ) { + } + pod::Transform<> getReference( pod::Transform<>& t ) { return t.reference ? *t.reference : t; - }), - UF_LUA_REGISTER_USERTYPE_DEFINE(lookAt, []( const pod::Transform<>& t, pod::Vector3f& at ) { + } + pod::Transform<> lookAt( const pod::Transform<>& t, pod::Vector3f& at ) { auto transform = t; return uf::transform::lookAt( transform, at ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE(getModel, []( const pod::Transform<>& t ) { + } + pod::Matrix4f getModel( const pod::Transform<>& t ) { return uf::transform::model( t ); - }) + } +} + +UF_LUA_REGISTER_USERTYPE(pod::Transform<>, + UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::position), + UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::scale), + UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::up), + UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::right), + UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::forward), + UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::orientation), + UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::model), + + UF_LUA_REGISTER_USERTYPE_DEFINE(move, UF_LUA_C_FUN(::binds::move) ), + UF_LUA_REGISTER_USERTYPE_DEFINE(rotate, UF_LUA_C_FUN(::binds::rotate)), + UF_LUA_REGISTER_USERTYPE_DEFINE(flatten, UF_LUA_C_FUN(::binds::flatten)), + UF_LUA_REGISTER_USERTYPE_DEFINE(reorient, UF_LUA_C_FUN(::binds::reorient)), + UF_LUA_REGISTER_USERTYPE_DEFINE(getReference, UF_LUA_C_FUN(::binds::getReference)), + UF_LUA_REGISTER_USERTYPE_DEFINE(lookAt, UF_LUA_C_FUN(::binds::lookAt)), + UF_LUA_REGISTER_USERTYPE_DEFINE(getModel, UF_LUA_C_FUN(::binds::getModel)) ) #endif \ No newline at end of file diff --git a/engine/src/ext/lua/usertypes/vector.cpp b/engine/src/ext/lua/usertypes/vector.cpp index a8eb6a6a..57874918 100644 --- a/engine/src/ext/lua/usertypes/vector.cpp +++ b/engine/src/ext/lua/usertypes/vector.cpp @@ -2,6 +2,91 @@ #if UF_USE_LUA #include +namespace binds { + namespace v3f { + float index( const pod::Vector3f& self, const size_t& index ) { + return self[index]; + } + float distance( pod::Vector3f& self, const pod::Vector3f& other ) { + return uf::vector::distance( self, other ); + } + pod::Vector3f add( const pod::Vector3f& left, const pod::Vector3f& right ) { + return uf::vector::add( left, right ); + } + pod::Vector3f sub( const pod::Vector3f& left, const pod::Vector3f& right ) { + return uf::vector::subtract( left, right ); + } + pod::Vector3f mul( const pod::Vector3f& left, const pod::Vector3f& right ) { + return uf::vector::multiply( left, right ); + } + pod::Vector3f div( const pod::Vector3f& left, const pod::Vector3f& right ) { + return uf::vector::divide( left, right ); + } + pod::Vector3f mulS( const pod::Vector3f& left, float right ) { + return uf::vector::multiply( left, right ); + } + pod::Vector3f divS( const pod::Vector3f& left, float right ) { + return uf::vector::divide( left, right ); + } + pod::Vector3f lerp( const pod::Vector3f& start, const pod::Vector3f& end, double delta ) { + return uf::vector::lerp( start, end, delta ); + } + pod::Vector3f normalize( const pod::Vector3f& self ) { + return uf::vector::normalize( self ); + } + float magnitude( const pod::Vector3f& self ) { + return uf::vector::magnitude( self ); + } + float dot( const pod::Vector3f& left, const pod::Vector3f& right ) { + return uf::vector::dot( left, right ); + } + std::string toString( pod::Vector3f& self ) { + return uf::string::toString( self ); + } + } + namespace v4f { + float index( const pod::Vector4f& self, const size_t& index ) { + return self[index]; + } + float distance( pod::Vector4f& self, const pod::Vector4f& other ) { + return uf::vector::distance( self, other ); + } + pod::Vector4f add( const pod::Vector4f& left, const pod::Vector4f& right ) { + return uf::vector::add( left, right ); + } + pod::Vector4f sub( const pod::Vector4f& left, const pod::Vector4f& right ) { + return uf::vector::subtract( left, right ); + } + pod::Vector4f mul( const pod::Vector4f& left, const pod::Vector4f& right ) { + return uf::vector::multiply( left, right ); + } + pod::Vector4f div( const pod::Vector4f& left, const pod::Vector4f& right ) { + return uf::vector::divide( left, right ); + } + pod::Vector4f mulS( const pod::Vector4f& left, float right ) { + return uf::vector::multiply( left, right ); + } + pod::Vector4f divS( const pod::Vector4f& left, float right ) { + return uf::vector::divide( left, right ); + } + pod::Vector4f lerp( const pod::Vector4f& start, const pod::Vector4f& end, double delta ) { + return uf::vector::lerp( start, end, delta ); + } + pod::Vector4f normalize( const pod::Vector4f& self ) { + return uf::vector::normalize( self ); + } + float magnitude( const pod::Vector4f& self ) { + return uf::vector::magnitude( self ); + } + float dot( const pod::Vector4f& left, const pod::Vector4f& right ) { + return uf::vector::dot( left, right ); + } + std::string toString( pod::Vector4f& self ) { + return uf::string::toString( self ); + } + } +} + UF_LUA_REGISTER_USERTYPE(pod::Vector3f, sol::call_constructor, sol::initializers( []( pod::Vector3f& self ) { @@ -17,45 +102,20 @@ UF_LUA_REGISTER_USERTYPE(pod::Vector3f, UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Vector3f::x), UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Vector3f::y), UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Vector3f::z), - UF_LUA_REGISTER_USERTYPE_DEFINE( v, []( pod::Vector3f& self, const size_t& index ) { - return self[index]; - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( distance, []( pod::Vector3f& self, const pod::Vector3f& other ) { - return uf::vector::distance( self, other ); - }), - sol::meta_function::addition, []( const pod::Vector3f& left, const pod::Vector3f& right ) { - return uf::vector::add( left, right ); - }, - sol::meta_function::subtraction, []( const pod::Vector3f& left, const pod::Vector3f& right ) { - return uf::vector::subtract( left, right ); - }, - sol::meta_function::multiplication, []( const pod::Vector3f& left, const pod::Vector3f& right ) { - return uf::vector::multiply( left, right ); - }, - sol::meta_function::multiplication, []( const pod::Vector3f& left, double right ) { - return uf::vector::multiply( left, right ); - }, - sol::meta_function::division, []( const pod::Vector3f& left, const pod::Vector3f& right ) { - return uf::vector::divide( left, right ); - }, - sol::meta_function::division, []( const pod::Vector3f& left, double right ) { - return uf::vector::divide( left, right ); - }, - UF_LUA_REGISTER_USERTYPE_DEFINE( lerp, []( const pod::Vector3f& start, const pod::Vector3f& end, double delta ) { - return uf::vector::lerp( start, end, delta ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( normalize, []( const pod::Vector3f& self ) { - return uf::vector::normalize( self ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( magnitude, []( const pod::Vector3f& self ) { - return uf::vector::magnitude( self ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( dot, []( const pod::Vector3f& left, const pod::Vector3f& right ) { - return uf::vector::dot( left, right ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, []( pod::Vector3f& self ) { - return uf::string::toString( self ); - }) + + UF_LUA_REGISTER_USERTYPE_DEFINE( v, UF_LUA_C_FUN( ::binds::v3f::index )), + UF_LUA_REGISTER_USERTYPE_DEFINE( distance, UF_LUA_C_FUN( ::binds::v3f::distance )), + sol::meta_function::addition, UF_LUA_C_FUN( ::binds::v3f::add ), + sol::meta_function::subtraction, UF_LUA_C_FUN( ::binds::v3f::sub ), + sol::meta_function::multiplication, UF_LUA_C_FUN( ::binds::v3f::mul ), + sol::meta_function::multiplication, UF_LUA_C_FUN( ::binds::v3f::mulS ), + sol::meta_function::division, UF_LUA_C_FUN( ::binds::v3f::div ), + sol::meta_function::division, UF_LUA_C_FUN( ::binds::v3f::divS ), + UF_LUA_REGISTER_USERTYPE_DEFINE( lerp, UF_LUA_C_FUN(::binds::v3f::lerp) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( normalize, UF_LUA_C_FUN(::binds::v3f::normalize) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( magnitude, UF_LUA_C_FUN(::binds::v3f::magnitude) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( dot, UF_LUA_C_FUN(::binds::v3f::dot) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, UF_LUA_C_FUN(::binds::v3f::toString) ) ) UF_LUA_REGISTER_USERTYPE(pod::Vector4f, sol::call_constructor, sol::initializers( @@ -73,47 +133,19 @@ UF_LUA_REGISTER_USERTYPE(pod::Vector4f, UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Vector4f::y), UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Vector4f::z), UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Vector4f::w), - UF_LUA_REGISTER_USERTYPE_DEFINE( v, []( pod::Vector4f& self, const size_t& index ) { - return self[index]; - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( distance, []( pod::Vector4f& self, const pod::Vector4f& other ) { - return uf::vector::distance( self, other ); - }), - sol::meta_function::addition, []( const pod::Vector4f& left, const pod::Vector4f& right ) { - return uf::vector::add( left, right ); - }, - sol::meta_function::subtraction, []( const pod::Vector4f& left, const pod::Vector4f& right ) { - return uf::vector::subtract( left, right ); - }, - sol::meta_function::multiplication, []( const pod::Vector4f& left, const pod::Vector4f& right ) { - return uf::vector::multiply( left, right ); - }, - sol::meta_function::multiplication, []( const pod::Vector4f& left, double right ) { - return uf::vector::multiply( left, right ); - }, - sol::meta_function::division, []( const pod::Vector4f& left, const pod::Vector4f& right ) { - return uf::vector::divide( left, right ); - }, - sol::meta_function::division, []( const pod::Vector4f& left, double right ) { - return uf::vector::divide( left, right ); - }, - UF_LUA_REGISTER_USERTYPE_DEFINE( lerp, []( const pod::Vector4f& start, const pod::Vector4f& end, double delta ) { - return uf::vector::lerp( start, end, delta ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( slerp, []( const pod::Vector4f& start, const pod::Vector4f& end, double delta ) { - return uf::vector::slerp( start, end, delta ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( normalize, []( const pod::Vector3f& self ) { - return uf::vector::normalize( self ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( magnitude, []( const pod::Vector3f& self ) { - return uf::vector::magnitude( self ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( dot, []( const pod::Vector3f& left, const pod::Vector3f& right ) { - return uf::vector::dot( left, right ); - }), - UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, []( pod::Vector4f& self ) { - return uf::string::toString( self ); - }) + + UF_LUA_REGISTER_USERTYPE_DEFINE( v, UF_LUA_C_FUN( ::binds::v4f::index )), + UF_LUA_REGISTER_USERTYPE_DEFINE( distance, UF_LUA_C_FUN( ::binds::v4f::distance )), + sol::meta_function::addition, UF_LUA_C_FUN( ::binds::v4f::add ), + sol::meta_function::subtraction, UF_LUA_C_FUN( ::binds::v4f::sub ), + sol::meta_function::multiplication, UF_LUA_C_FUN( ::binds::v4f::mul ), + sol::meta_function::multiplication, UF_LUA_C_FUN( ::binds::v4f::mulS ), + sol::meta_function::division, UF_LUA_C_FUN( ::binds::v4f::div ), + sol::meta_function::division, UF_LUA_C_FUN( ::binds::v4f::divS ), + UF_LUA_REGISTER_USERTYPE_DEFINE( lerp, UF_LUA_C_FUN(::binds::v4f::lerp) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( normalize, UF_LUA_C_FUN(::binds::v4f::normalize) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( magnitude, UF_LUA_C_FUN(::binds::v4f::magnitude) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( dot, UF_LUA_C_FUN(::binds::v4f::dot) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, UF_LUA_C_FUN(::binds::v4f::toString) ) ) #endif \ No newline at end of file diff --git a/engine/src/ext/opengl/commands.cpp b/engine/src/ext/opengl/commands.cpp index 423acd60..c27a42f8 100644 --- a/engine/src/ext/opengl/commands.cpp +++ b/engine/src/ext/opengl/commands.cpp @@ -359,7 +359,7 @@ size_t ext::opengl::CommandBuffer::size() const { return infos.size(); } -void ext::opengl::CommandBuffer::bindUniform( const ext::opengl::Buffer::Descriptor& descriptor ) { +pod::Matrix4f ext::opengl::CommandBuffer::bindUniform( const ext::opengl::Buffer::Descriptor& descriptor ) { #if UF_USE_OPENGL_FIXED_FUNCTION pod::Uniform* uniform = (pod::Uniform*) (device->getBuffer( descriptor.buffer ) + descriptor.offset); @@ -368,6 +368,8 @@ void ext::opengl::CommandBuffer::bindUniform( const ext::opengl::Buffer::Descrip GL_ERROR_CHECK(glMatrixMode(GL_MODELVIEW)); GL_ERROR_CHECK(glLoadMatrixf( &uniform->modelView[0] )); + + return uniform->projection * uniform->modelView; #endif } #if 0 @@ -529,7 +531,7 @@ void ext::opengl::CommandBuffer::draw( const ext::opengl::CommandBuffer::InfoDra } #endif void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::InfoDraw& drawInfo ) { - bindUniform( drawInfo.uniformBuffer ); + auto projectionViewMatrix = bindUniform( drawInfo.uniformBuffer ); size_t indices = drawInfo.descriptor.indices; size_t indicesStride = drawInfo.descriptor.geometry.attributes.index.size; @@ -543,6 +545,12 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer:: GL_ERROR_CHECK(glFrontFace(drawInfo.descriptor.frontFace)); GL_ERROR_CHECK(glCullFace(drawInfo.descriptor.cullMode)); } + if ( drawInfo.descriptor.depth.test ) { + GL_ERROR_CHECK(glEnable(GL_DEPTH_TEST)); + } else { + GL_ERROR_CHECK(glDisable(GL_DEPTH_TEST)); + } + GL_ERROR_CHECK(glDepthMask(drawInfo.descriptor.depth.write ? GL_TRUE : GL_FALSE)); // CPU-buffer based command dispatching void* vertexPointer = (void*) ( device->getBuffer( drawInfo.vertexBuffer.buffer ) + drawInfo.vertexBuffer.offset ); @@ -586,7 +594,47 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer:: if ( drawInfo.attributes.color ) GL_ERROR_CHECK(glColorPointer(3, GL_FLOAT, vertexStride, vertexPointer + drawInfo.attributes.color)); GL_ERROR_CHECK(glVertexPointer(3, GL_FLOAT, vertexStride, vertexPointer + drawInfo.attributes.position)); - GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, indices, indicesType, indicesPointer)); + // frustrum culling + if ( ext::opengl::settings::experimental::frustrumCull ) { + std::vector unculled; + unculled.reserve(indices); + for ( size_t currentIndex = 0; currentIndex < indices; currentIndex += 3 ) { + const pod::Vector3f& positionA = *((pod::Vector3f*) ((vertexPointer + (indicesPointer[currentIndex+0] * vertexStride)) + drawInfo.attributes.position)); + const pod::Vector3f& positionB = *((pod::Vector3f*) ((vertexPointer + (indicesPointer[currentIndex+2] * vertexStride)) + drawInfo.attributes.position)); + const pod::Vector3f& positionC = *((pod::Vector3f*) ((vertexPointer + (indicesPointer[currentIndex+1] * vertexStride)) + drawInfo.attributes.position)); + + bool inside = false; + pod::Vector3f translated = uf::matrix::multiply( projectionViewMatrix, positionA, 1, true ); + static constexpr pod::Vector3f min{-1.5,-1.5,-1.5}; + static constexpr pod::Vector3f max{ 1.5, 1.5, 1.5}; + if ( min.x <= translated.x && min.y <= translated.y && min.z <= translated.z && translated.x <= max.x && translated.y <= max.y && translated.z <= max.z ) inside = true; + // if ( min <= translated && translated <= max ) inside = true; + else { + pod::Vector3f translated = uf::matrix::multiply( projectionViewMatrix, positionB, 1, true ); + if ( min.x <= translated.x && min.y <= translated.y && min.z <= translated.z && translated.x <= max.x && translated.y <= max.y && translated.z <= max.z ) inside = true; + // if ( min <= translated && translated <= max ) inside = true; + else { + pod::Vector3f translated = uf::matrix::multiply( projectionViewMatrix, positionC, 1, true ); + if ( min.x <= translated.x && min.y <= translated.y && min.z <= translated.z && translated.x <= max.x && translated.y <= max.y && translated.z <= max.z ) inside = true; + // if ( min <= translated && translated <= max ) inside = true; + } + } + if ( inside ) { + unculled.emplace_back(indicesPointer[currentIndex+0]); + unculled.emplace_back(indicesPointer[currentIndex+1]); + unculled.emplace_back(indicesPointer[currentIndex+2]); + } + } + GLenum indicesType = GL_UNSIGNED_INT; + switch ( sizeof(uf::renderer::index_t) ) { + case sizeof(uint32_t): indicesType = GL_UNSIGNED_INT; break; + case sizeof(uint16_t): indicesType = GL_UNSIGNED_SHORT; break; + case sizeof(uint8_t): indicesType = GL_UNSIGNED_BYTE; break; + } + GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, unculled.size(), indicesType, &unculled[0])); + } else { + GL_ERROR_CHECK(glDrawElements(GL_TRIANGLES, indices, indicesType, indicesPointer)); + } if ( drawInfo.auxTexture.image ) { #if UF_ENV_DREAMCAST diff --git a/engine/src/ext/opengl/graphic.cpp b/engine/src/ext/opengl/graphic.cpp index 9a88047c..72206248 100644 --- a/engine/src/ext/opengl/graphic.cpp +++ b/engine/src/ext/opengl/graphic.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #if 0 #include @@ -1362,7 +1363,6 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, size_t pass, si return this->record( commandBuffer, descriptor, pass, draw ); } -#include void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, GraphicDescriptor& descriptor, size_t pass, size_t draw ) { if ( !process ) return; #if 0 @@ -1376,20 +1376,17 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, GraphicDescript return; } pipeline.record(*this, commandBuffer, pass, draw); -#endif - int32_t vertexBufferIndex = -1; - int32_t uniformBufferIndex = -1; - int32_t storageBufferIndex = -1; +#endif Buffer::Descriptor vertexBuffer = {}; Buffer::Descriptor indexBuffer = {}; Buffer::Descriptor uniformBuffer = {}; - size_t vertexBufferSize = {}; - size_t indexBufferSize = {}; - size_t uniformBufferSize = {}; + std::vector storageBuffers; + for ( auto& buffer : buffers ) { - if ( buffer.usage & uf::renderer::enums::Buffer::VERTEX ) { vertexBuffer = buffer.descriptor; vertexBufferSize = buffer.size; } - if ( buffer.usage & uf::renderer::enums::Buffer::INDEX ) { indexBuffer = buffer.descriptor; indexBufferSize = buffer.size; } - if ( buffer.usage & uf::renderer::enums::Buffer::UNIFORM ) { uniformBuffer = buffer.descriptor; uniformBufferSize = buffer.size; } + if ( buffer.usage & uf::renderer::enums::Buffer::VERTEX ) { vertexBuffer = buffer.descriptor; } + if ( buffer.usage & uf::renderer::enums::Buffer::INDEX ) { indexBuffer = buffer.descriptor; } + if ( buffer.usage & uf::renderer::enums::Buffer::UNIFORM ) { uniformBuffer = buffer.descriptor; } + if ( buffer.usage & uf::renderer::enums::Buffer::STORAGE ) { storageBuffers.emplace_back(buffer.descriptor); } } if ( !vertexBuffer.buffer || !indexBuffer.buffer ) return; @@ -1403,7 +1400,7 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, GraphicDescript for ( auto& attribute : descriptor.geometry.attributes.descriptor ) { if ( attribute.name == "position" ) vertexAttributePosition = attribute; // else if ( attribute.name == "normal" ) vertexAttributeNormal = attribute; - else if ( attribute.name == "color" ) vertexAttributeColor = attribute; +// else if ( attribute.name == "color" ) vertexAttributeColor = attribute; else if ( attribute.name == "uv" ) vertexAttributeUv = attribute; else if ( attribute.name == "st" ) vertexAttributeSt = attribute; else if ( attribute.name == "id" ) vertexAttributeId = attribute; @@ -1431,6 +1428,7 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, GraphicDescript if ( vertexAttributeNormal.name != "" ) drawCommandInfo.attributes.normal = vertexAttributeNormal.offset; if ( vertexAttributeColor.name != "" ) drawCommandInfo.attributes.color = vertexAttributeColor.offset; + // split up our mesh by textures, if the right attribute exists if ( vertexAttributeId.name != "" ) { struct TextureMapping { @@ -1440,6 +1438,22 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, GraphicDescript }; std::vector mappings; TextureMapping currentMapping; + + pod::Texture::Storage* storageBufferTextures = NULL; + pod::Material::Storage* storageBufferMaterials = NULL; + size_t storageBufferTexturesSize = 0; + size_t storageBufferMaterialsSize = 0; + + if ( storageBuffers.size() >= 2 ) { + Buffer::Descriptor storageBufferTexturesDescriptor = storageBuffers[storageBuffers.size() - 1]; + Buffer::Descriptor storageBufferMaterialsDescriptor = storageBuffers[storageBuffers.size() - 2]; + + storageBufferTextures = (pod::Texture::Storage*) ( device->getBuffer( storageBufferTexturesDescriptor.buffer ) + storageBufferTexturesDescriptor.offset ); + storageBufferMaterials = (pod::Material::Storage*) ( device->getBuffer( storageBufferMaterialsDescriptor.buffer ) + storageBufferMaterialsDescriptor.offset ); + + storageBufferTexturesSize = storageBufferTexturesDescriptor.range / sizeof(pod::Texture::Storage); + storageBufferMaterialsSize = storageBufferMaterialsDescriptor.range / sizeof(pod::Material::Storage); + } bool useLightmap = false; for ( size_t currentIndex = 0; currentIndex < indices; ++currentIndex ) { @@ -1451,8 +1465,18 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, GraphicDescript const pod::Vector2f& st = *((pod::Vector2f*) (vertices + vertexAttributeSt.offset)); if ( st > pod::Vector2f{0,0} ) useLightmap = true; } - + size_t materialId = id.y; size_t textureId = id.y; + if ( storageBufferMaterials && 0 <= materialId && materialId < storageBufferMaterialsSize ) { + auto& material = storageBufferMaterials[materialId]; + size_t textureIndex = material.indexAlbedo; + if ( 0 <= textureIndex && textureIndex < storageBufferTexturesSize ) { + auto& texture = storageBufferTextures[textureIndex]; + if ( 0 <= texture.index && texture.index < this->material.textures.size() ) { + textureId = texture.index; + } + } + } if ( currentMapping.texture != textureId ) { if ( currentMapping.range > 0 ) mappings.emplace_back(currentMapping); currentMapping.offset += currentMapping.range; @@ -1467,7 +1491,7 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, GraphicDescript drawCommandInfo.auxTexture = material.textures.back().descriptor; } for ( auto& mapping : mappings ) { - if ( mapping.range == 0 || mapping.texture >= material.textures.size() ) continue; + if ( mapping.range == 0 || !( 0 <= mapping.texture && mapping.texture < material.textures.size()) ) continue; drawCommandInfo.texture = material.textures[mapping.texture].descriptor; drawCommandInfo.descriptor.indices = mapping.range; drawCommandInfo.indexBuffer.offset = indexBuffer.offset + sizeof(uf::renderer::index_t) * mapping.offset; @@ -1621,6 +1645,12 @@ void ext::opengl::GraphicDescriptor::parse( ext::json::Value& metadata ) { cullMode = uf::renderer::enums::CullMode::BOTH; } } + + if ( ext::json::isObject(metadata["depth test"]) ) { + if ( metadata["depth test"]["test"].is() ) depth.test = metadata["depth test"]["test"].as(); + if ( metadata["depth test"]["write"].is() ) depth.write = metadata["depth test"]["write"].as(); + } + if ( metadata["indices"].is() ) { indices = metadata["indices"].as(); } diff --git a/engine/src/ext/opengl/opengl.cpp b/engine/src/ext/opengl/opengl.cpp index 3115cef9..1f722add 100644 --- a/engine/src/ext/opengl/opengl.cpp +++ b/engine/src/ext/opengl/opengl.cpp @@ -44,6 +44,7 @@ bool ext::opengl::settings::experimental::deferredAliasOutputToSwapchain = true; bool ext::opengl::settings::experimental::multiview = true; bool ext::opengl::settings::experimental::vsync = true; bool ext::opengl::settings::experimental::hdr = true; +bool ext::opengl::settings::experimental::frustrumCull = false; GLhandle(VkColorSpaceKHR) ext::opengl::settings::formats::colorSpace; ext::opengl::enums::Format::type_t ext::opengl::settings::formats::color = ext::opengl::enums::Format::R8G8B8A8_UNORM; @@ -347,6 +348,7 @@ void UF_API ext::opengl::tick(){ void UF_API ext::opengl::render(){ ext::opengl::mutex.lock(); #if !UF_ENV_DREAMCAST +#if 0 if ( hasRenderMode("Gui", true) ) { RenderMode& primary = getRenderMode("Gui", true); auto it = std::find( renderModes.begin(), renderModes.end(), &primary ); @@ -361,6 +363,7 @@ void UF_API ext::opengl::render(){ auto it = std::find( renderModes.begin(), renderModes.end(), &primary ); if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() ); } +#endif ext::opengl::device.activateContext(); #endif for ( auto& renderMode : renderModes ) { diff --git a/engine/src/ext/opengl/rendermode.cpp b/engine/src/ext/opengl/rendermode.cpp index 4892d361..6799bcb1 100644 --- a/engine/src/ext/opengl/rendermode.cpp +++ b/engine/src/ext/opengl/rendermode.cpp @@ -45,7 +45,7 @@ std::vector ext::opengl::RenderMode::getBlitters() { ext::opengl::GraphicDescriptor ext::opengl::RenderMode::bindGraphicDescriptor( const ext::opengl::GraphicDescriptor& reference, size_t pass ) { ext::opengl::GraphicDescriptor descriptor = reference; - descriptor.renderMode = this->getName(); +// descriptor.renderMode = this->getName(); descriptor.subpass = pass; descriptor.parse( metadata ); return descriptor; @@ -57,7 +57,6 @@ void ext::opengl::RenderMode::createCommandBuffers() { this->execute = true; std::vector graphics; -if ( uf::scene::useGraph ) { auto graph = uf::scene::generateGraph(); for ( auto entity : graph ) { if ( !entity->hasComponent() ) continue; @@ -65,17 +64,6 @@ if ( uf::scene::useGraph ) { if ( !graphic.initialized || !graphic.process ) continue; graphics.push_back(&graphic); } -} else { - for ( uf::Scene* scene : uf::scene::scenes ) { - if ( !scene ) continue; - scene->process([&]( uf::Entity* entity ) { - if ( !entity->hasComponent() ) return; - ext::opengl::Graphic& graphic = entity->getComponent(); - if ( !graphic.initialized || !graphic.process ) return; - graphics.push_back(&graphic); - }); - } -} this->synchronize(); // bindPipelines( graphics ); @@ -101,7 +89,6 @@ void ext::opengl::RenderMode::bindPipelines() { this->execute = true; std::vector graphics; -if ( uf::scene::useGraph ) { auto graph = uf::scene::generateGraph(); for ( auto entity : graph ) { if ( !entity->hasComponent() ) continue; @@ -109,18 +96,6 @@ if ( uf::scene::useGraph ) { if ( !graphic.initialized || !graphic.process ) continue; graphics.push_back(&graphic); } -} else { - for ( uf::Scene* scene : uf::scene::scenes ) { - if ( !scene ) continue; - scene->process([&]( uf::Entity* entity ) { - if ( !entity->hasComponent() ) return; - ext::opengl::Graphic& graphic = entity->getComponent(); - if ( !graphic.initialized ) return; - if ( !graphic.process ) return; - graphics.push_back(&graphic); - }); - } -} this->synchronize(); this->bindPipelines( graphics ); @@ -133,6 +108,8 @@ void ext::opengl::RenderMode::bindPipelines( const std::vectormostRecentCommandPoolId); commands.submit(); + + if ( ext::opengl::renderModes.back() != this ) return; + #if UF_ENV_DREAMCAST - //UF_TIMER_TRACE_INIT(); #if UF_USE_OPENGL_GLDC glKosSwapBuffers(); - // profiler_print_stats(); #else glutSwapBuffers(); #endif - //UF_TIMER_TRACE("==== SWAP BUFFER TIME ==== "); #else - if ( device ) { - device->activateContext().display(); - } + if ( device ) device->activateContext().display(); #endif + auto& scene = uf::scene::getCurrentScene(); + auto& sceneMetadata = scene.getComponent(); + + CommandBuffer::InfoClear clearCommandInfo = {}; + clearCommandInfo.type = enums::Command::CLEAR; + clearCommandInfo.color = {0.0f, 0.0f, 0.0f, 0.0f}; + clearCommandInfo.depth = uf::Camera::USE_REVERSE_INFINITE_PROJECTION ? 0.0f : 1.0f; + clearCommandInfo.bits = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; + if ( !ext::json::isNull( sceneMetadata["system"]["renderer"]["clear values"][0] ) ) { + clearCommandInfo.color = uf::vector::decode( sceneMetadata["system"]["renderer"]["clear values"][0], pod::Vector4f{0,0,0,0} ); + } + if ( !ext::json::isNull( sceneMetadata["light"]["ambient"] ) ) { + clearCommandInfo.color = uf::vector::decode( sceneMetadata["light"]["ambient"], pod::Vector4f{0,0,0,0} ); + // auto ambient = uf::vector::decode( sceneMetadata["light"]["ambient"], pod::Vector4f{1,1,1,1} ); + // GL_ERROR_CHECK(glLightfv(GL_LIGHT0, GL_AMBIENT, &ambient[0])); + } + + GL_ERROR_CHECK(glClearColor(clearCommandInfo.color[0], clearCommandInfo.color[1], clearCommandInfo.color[2], clearCommandInfo.color[3])); + GL_ERROR_CHECK(glClearDepth(clearCommandInfo.depth)); + GL_ERROR_CHECK(glClear(clearCommandInfo.bits)); + } void ext::opengl::RenderMode::initialize( Device& device ) { diff --git a/engine/src/ext/opengl/rendermodes/base.cpp b/engine/src/ext/opengl/rendermodes/base.cpp index 55c134ac..9ed2b837 100644 --- a/engine/src/ext/opengl/rendermodes/base.cpp +++ b/engine/src/ext/opengl/rendermodes/base.cpp @@ -24,6 +24,7 @@ void ext::opengl::BaseRenderMode::createCommandBuffers( const std::vector 1 ) return; - if ( ext::opengl::renderModes.back() != this ) return; +// if ( ext::opengl::renderModes.back() != this ) return; ext::opengl::RenderMode::render(); } diff --git a/engine/src/ext/opengl/rendermodes/deferred.cpp b/engine/src/ext/opengl/rendermodes/deferred.cpp index 5178dd03..78957783 100644 --- a/engine/src/ext/opengl/rendermodes/deferred.cpp +++ b/engine/src/ext/opengl/rendermodes/deferred.cpp @@ -43,13 +43,14 @@ void ext::opengl::DeferredRenderMode::createCommandBuffers( const std::vector(); + std::string target = metadata["target"].as(); + if ( type == "depth" ) { + // descriptor.cullMode = VK_CULL_MODE_NONE; + } + // invalidate + if ( target != "" && descriptor.renderMode != this->getName() && descriptor.renderMode != target ) { + descriptor.invalidated = true; + } else { + descriptor.renderMode = this->getName(); + } return descriptor; } void ext::opengl::RenderTargetRenderMode::initialize( Device& device ) { ext::opengl::RenderMode::initialize( device ); + this->setTarget( this->getName() ); } void ext::opengl::RenderTargetRenderMode::tick() { @@ -46,10 +57,9 @@ void ext::opengl::RenderTargetRenderMode::tick() { } void ext::opengl::RenderTargetRenderMode::destroy() { ext::opengl::RenderMode::destroy(); - blitter.destroy(); } void ext::opengl::RenderTargetRenderMode::render() { - auto& commands = getCommands( this->mostRecentCommandPoolId ); + ext::opengl::RenderMode::render(); } void ext::opengl::RenderTargetRenderMode::pipelineBarrier( GLhandle(VkCommandBuffer) commandBuffer, uint8_t state ) { } @@ -59,25 +69,29 @@ void ext::opengl::RenderTargetRenderMode::createCommandBuffers( const std::vecto auto& commands = getCommands(); commands.start(); { + #if 0 CommandBuffer::InfoClear clearCommandInfo = {}; clearCommandInfo.type = enums::Command::CLEAR; clearCommandInfo.color = {0.0f, 0.0f, 0.0f, 0.0f}; clearCommandInfo.depth = uf::Camera::USE_REVERSE_INFINITE_PROJECTION ? 0.0f : 1.0f; clearCommandInfo.bits = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; commands.record(clearCommandInfo); - + #endif + #if 0 CommandBuffer::InfoViewport viewportCommandInfo = {}; viewportCommandInfo.type = enums::Command::VIEWPORT; viewportCommandInfo.corner = pod::Vector2ui{0, 0}; viewportCommandInfo.size = pod::Vector2ui{width, height}; commands.record(viewportCommandInfo); + #endif size_t currentSubpass = 0; size_t currentPass = 0; size_t currentDraw = 0; for ( auto graphic : graphics ) { - if ( graphic->descriptor.renderMode != this->getName() ) continue; + if ( graphic->descriptor.renderMode != this->getTarget() ) continue; GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass); + if ( descriptor.invalidated ) continue; graphic->record( commands, descriptor, currentPass, currentDraw++ ); } } commands.end(); diff --git a/engine/src/ext/opengl/texture.cpp b/engine/src/ext/opengl/texture.cpp index e3de6cb2..d87f9cb3 100644 --- a/engine/src/ext/opengl/texture.cpp +++ b/engine/src/ext/opengl/texture.cpp @@ -81,7 +81,7 @@ void ext::opengl::Texture::loadFromFile( return loadFromFile( filename, ext::opengl::device, format ); } void ext::opengl::Texture::loadFromImage( - uf::Image& image, + const uf::Image& image, enums::Format::type_t format ) { return loadFromImage( image, ext::opengl::device, format ); @@ -96,13 +96,14 @@ void ext::opengl::Texture::loadFromFile( return loadFromImage( image, device, format ); } void ext::opengl::Texture::loadFromImage( - uf::Image& image, + const uf::Image& image, Device& device, enums::Format::type_t format ) { - if ( image.getFormat() > 0 ) { +// UF_DEBUG_MSG( image.getFilename() << " | " << std::bitset<32>(image.getFormat()) ); + if ( image.getFormat() != 0 ) { internalFormat = image.getFormat(); - } else + } else { switch ( image.getChannels() ) { // R case 1: @@ -155,7 +156,7 @@ void ext::opengl::Texture::loadFromImage( UF_EXCEPTION("unsupported channels of " + std::to_string(image.getChannels())); break; } - + } // convert to power of two //image.padToPowerOfTwo(); @@ -195,6 +196,7 @@ void ext::opengl::Texture::fromBuffers( Device& device ) { this->initialize(device, viewType, texWidth, texHeight, texDepth, layers); + this->format = format; #if !UF_ENV_DREAMCAST if ( this->mips == 0 ) { @@ -261,16 +263,12 @@ void ext::opengl::Texture::update( void* data, size_t bufferSize, uint32_t layer GLenum format = GL_RGBA; GLenum type = GL_UNSIGNED_BYTE; switch ( this->format ) { - #if !UF_ENV_DREAMCAST case enums::Format::R8_UNORM: - format = GL_RED; + format = GL_LUMINANCE; break; - #endif - #if !UF_ENV_DREAMCAST case enums::Format::R8G8_UNORM: - format = GL_RG; + format = GL_LUMINANCE_ALPHA; break; - #endif case enums::Format::R8G8B8_UNORM: format = GL_RGB; break; diff --git a/engine/src/ext/vulkan/rendermode.cpp b/engine/src/ext/vulkan/rendermode.cpp index c10f38b8..55ff5336 100644 --- a/engine/src/ext/vulkan/rendermode.cpp +++ b/engine/src/ext/vulkan/rendermode.cpp @@ -190,7 +190,6 @@ void ext::vulkan::RenderMode::createCommandBuffers() { this->execute = true; std::vector graphics; -if ( uf::scene::useGraph ) { auto graph = uf::scene::generateGraph(); for ( auto entity : graph ) { if ( !entity->hasComponent() ) continue; @@ -198,17 +197,6 @@ if ( uf::scene::useGraph ) { if ( !graphic.initialized || !graphic.process ) continue; graphics.push_back(&graphic); } -} else { - for ( uf::Scene* scene : uf::scene::scenes ) { - if ( !scene ) continue; - scene->process([&]( uf::Entity* entity ) { - if ( !entity->hasComponent() ) return; - ext::vulkan::Graphic& graphic = entity->getComponent(); - if ( !graphic.initialized || !graphic.process ) return; - graphics.push_back(&graphic); - }); - } -} this->synchronize(); // bindPipelines( graphics ); @@ -242,7 +230,6 @@ void ext::vulkan::RenderMode::bindPipelines() { this->execute = true; std::vector graphics; -if ( uf::scene::useGraph ) { auto graph = uf::scene::generateGraph(); for ( auto entity : graph ) { if ( !entity->hasComponent() ) continue; @@ -251,19 +238,6 @@ if ( uf::scene::useGraph ) { // if ( graphic.descriptor.renderMode != "" && graphic.descriptor.renderMode != this->getName() ) continue; graphics.push_back(&graphic); } -} else { - for ( uf::Scene* scene : uf::scene::scenes ) { - if ( !scene ) continue; - scene->process([&]( uf::Entity* entity ) { - if ( !entity->hasComponent() ) return; - ext::vulkan::Graphic& graphic = entity->getComponent(); - if ( !graphic.initialized ) return; - if ( !graphic.process ) return; - // if ( graphic.descriptor.renderMode != "" && graphic.descriptor.renderMode != this->getName() ) return; - graphics.push_back(&graphic); - }); - } -} this->synchronize(); this->bindPipelines( graphics ); } diff --git a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp index a6bfa439..56530185 100644 --- a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp @@ -32,27 +32,16 @@ ext::vulkan::GraphicDescriptor ext::vulkan::RenderTargetRenderMode::bindGraphicD ext::vulkan::GraphicDescriptor descriptor = ext::vulkan::RenderMode::bindGraphicDescriptor(reference, pass); descriptor.parse(metadata["descriptor"]); std::string type = metadata["type"].as(); + std::string target = metadata["target"].as(); if ( type == "depth" ) { descriptor.cullMode = VK_CULL_MODE_NONE; } - std::string target = metadata["target"].as(); // invalidate -// if ( ( target == "" && descriptor.renderMode != this->getName() ) || ( target != "" && descriptor.renderMode != target ) ) { if ( target != "" && descriptor.renderMode != this->getName() && descriptor.renderMode != target ) { descriptor.invalidated = true; } else { descriptor.renderMode = this->getName(); } -/* - // allows for "easy" remapping for indices ranges - if ( ext::json::isObject( metadata["renderMode"]["target"][std::to_string(descriptor.indices)] ) ) { - auto& map = metadata["renderMode"]["target"][std::to_string(descriptor.indices)]; - std::cout << "Replacing " << descriptor.indices; - descriptor.indices = map["size"].as(); - descriptor.offsets.index = map["offset"].as(); - std::cout << " with " << descriptor.offsets.index << " + " << descriptor.indices << std::endl; - } -*/ return descriptor; } diff --git a/engine/src/ext/vulkan/texture.cpp b/engine/src/ext/vulkan/texture.cpp index 5d4b4461..124ce763 100644 --- a/engine/src/ext/vulkan/texture.cpp +++ b/engine/src/ext/vulkan/texture.cpp @@ -268,75 +268,10 @@ void ext::vulkan::Texture::loadFromFile( ) { uf::Image image; image.open( filename ); - switch ( image.getChannels() ) { - // R - case 1: - switch ( image.getBpp() ) { - case 8: - format = VK_FORMAT_R8_UNORM; - break; - default: - UF_EXCEPTION("unsupported BPP of " + std::to_string(image.getBpp())); - break; - } - break; - // RGB - case 3: - switch ( image.getBpp() ) { - case 24: - format = VK_FORMAT_R8G8B8_UNORM; - break; - default: - UF_EXCEPTION("unsupported BPP of " + std::to_string(image.getBpp())); - break; - } - break; - // RGBA - case 4: - switch ( image.getBpp() ) { - case 32: - format = VK_FORMAT_R8G8B8A8_UNORM; - break; - default: - UF_EXCEPTION("unsupported BPP of " + std::to_string(image.getBpp())); - break; - } - break; - default: - UF_EXCEPTION("unsupported channels of " + std::to_string(image.getChannels())); - break; - } -/* - if (device.features.textureCompressionBC) { - format = VK_FORMAT_BC3_UNORM_BLOCK; - } - else if (device.features.textureCompressionASTC_LDR) { - format = VK_FORMAT_ASTC_8x8_UNORM_BLOCK; - } - else if (device.features.textureCompressionETC2) { - format = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; - } - else { - UF_EXCEPTION("VK_ERROR_FEATURE_NOT_PRESENT"); - } -*/ - - // convert to power of two - //image.padToPowerOfTwo(); - - this->fromBuffers( - (void*) image.getPixelsPtr(), - image.getPixels().size(), - format, - image.getDimensions()[0], - image.getDimensions()[1], - device, - imageUsageFlags, - imageLayout - ); + return loadFromImage( image, device, format, imageUsageFlags, imageLayout ); } void ext::vulkan::Texture::loadFromImage( - uf::Image& image, + const uf::Image& image, VkFormat format, VkImageUsageFlags imageUsageFlags, VkImageLayout imageLayout @@ -344,7 +279,7 @@ void ext::vulkan::Texture::loadFromImage( return loadFromImage( image, ext::vulkan::device, format, imageUsageFlags, imageLayout ); } void ext::vulkan::Texture::loadFromImage( - uf::Image& image, + const uf::Image& image, Device& device, VkFormat format, VkImageUsageFlags imageUsageFlags, diff --git a/engine/src/ext/vulkan/vulkan.cpp b/engine/src/ext/vulkan/vulkan.cpp index ef077c95..1d8345cd 100644 --- a/engine/src/ext/vulkan/vulkan.cpp +++ b/engine/src/ext/vulkan/vulkan.cpp @@ -36,6 +36,7 @@ bool ext::vulkan::settings::experimental::deferredAliasOutputToSwapchain = true; bool ext::vulkan::settings::experimental::multiview = true; bool ext::vulkan::settings::experimental::vsync = true; bool ext::vulkan::settings::experimental::hdr = true; +bool ext::vulkan::settings::experimental::frustrumCull = false; VkColorSpaceKHR ext::vulkan::settings::formats::colorSpace; ext::vulkan::enums::Format::type_t ext::vulkan::settings::formats::color = ext::vulkan::enums::Format::R8G8B8A8_UNORM; diff --git a/engine/src/ext/xatlas/xatlas.cpp b/engine/src/ext/xatlas/xatlas.cpp index 42d8255e..2941a524 100644 --- a/engine/src/ext/xatlas/xatlas.cpp +++ b/engine/src/ext/xatlas/xatlas.cpp @@ -44,13 +44,13 @@ pod::Vector2ui UF_API ext::xatlas::unwrap( pod::Graph& graph ) { } ::xatlas::ChartOptions chartOptions{}; - chartOptions.useInputMeshUvs = true; +// chartOptions.useInputMeshUvs = true; ::xatlas::PackOptions packOptions{}; // packOptions.bruteForce = true; // packOptions.resolution = resolution; // packOptions.texelsPerUnit = 64.0f; // packOptions.blockAlign = true; - packOptions.bilinear = true; +// packOptions.bilinear = true; ::xatlas::Generate(atlas, chartOptions, packOptions); auto oldMeshes = std::move( graph.meshes ); diff --git a/engine/src/utils/image/atlas.cpp b/engine/src/utils/image/atlas.cpp index a2bfe53a..7fa5b2d9 100644 --- a/engine/src/utils/image/atlas.cpp +++ b/engine/src/utils/image/atlas.cpp @@ -1,36 +1,55 @@ #include +#include #include -void uf::Atlas::addImage( const uf::Image& _image, bool regenerate ) { - auto& image = this->m_images.emplace_back( _image ); - if ( regenerate ) this->generate(); -} -void uf::Atlas::addImage( uf::Image&& _image, bool regenerate ) { - auto& image = this->m_images.emplace_back( _image ); - if ( regenerate ) this->generate(); -} -void uf::Atlas::addImage( const uint8_t* pointer, const pod::Vector2ui& size, std::size_t bpp, std::size_t channels, bool flip, bool regenerate ) { - auto& image = this->m_images.emplace_back(); - image.loadFromBuffer( pointer, size, bpp, channels, flip ); - if ( regenerate ) this->generate(); +uf::Atlas::hash_t uf::Atlas::addImage( const uf::Image& _image, bool regenerate ) { + size_t index = this->m_tiles.size(); + auto hash = _image.getHash(); + if ( this->m_tiles.count( hash ) > 0 ) return hash; + auto& tile = this->m_tiles[hash]; + tile.image = _image; + tile.identifier.hash = hash; + tile.identifier.index = index; + if ( regenerate ) this->generate(); + return hash; } -void uf::Atlas::generate( float padding ) { - return generate( this->m_images, padding ); +uf::Atlas::hash_t uf::Atlas::addImage( uf::Image&& _image, bool regenerate ) { + size_t index = this->m_tiles.size(); + auto hash = _image.getHash(); + if ( this->m_tiles.count( hash ) > 0 ) return hash; + + auto& tile = this->m_tiles[hash]; + tile.image = _image; + tile.identifier.hash = hash; + tile.identifier.index = index; + if ( regenerate ) this->generate(); + return hash; +} +uf::Atlas::hash_t uf::Atlas::addImage( const uint8_t* pointer, const pod::Vector2ui& size, std::size_t bpp, std::size_t channels, bool flip, bool regenerate ) { + uf::Image image; + image.loadFromBuffer( pointer, size, bpp, channels, flip ); + return this->addImage( std::move( image ), regenerate ); } void uf::Atlas::generate( const uf::Atlas::images_t& images, float padding ) { - if ( images.empty() ) return; - // destroy atlas - this->m_image.clear(); + for ( auto& image : images ) this->addImage( image, false ); + generate( padding ); +} +void uf::Atlas::generate( float padding ) { + if ( this->m_tiles.empty() ) return; - BinPack2D::ContentAccumulator queue; + BinPack2D::CanvasArray internalAtlas; + BinPack2D::ContentAccumulator queue, stored, remainder; pod::Vector2ui size = {0,0}; pod::Vector3ui largest = {0,0,0}; size_t index = 0; size_t area = 0; - for ( auto& image : images ) { - auto& dim = image.getDimensions(); - queue += BinPack2D::Content({index++}, BinPack2D::Coord(), BinPack2D::Size(dim.x, dim.y), false ); + size_t channels = 1; + for ( auto pair : this->m_tiles ) { + auto& tile = pair.second; + auto& dim = tile.image.getDimensions(); + channels = std::max( channels, tile.image.getChannels() ); + queue += BinPack2D::Content(tile.identifier, BinPack2D::Coord(), BinPack2D::Size(dim.x, dim.y), false ); size += dim; area += dim.x * dim.y; if ( area >= largest.z ) { @@ -39,10 +58,9 @@ void uf::Atlas::generate( const uf::Atlas::images_t& images, float padding ) { } } size_t tries = 16; - BinPack2D::ContentAccumulator stored, remainder; do { { - // size_t area = largest.x * largest.y * images.size(); + // size_t area = largest.x * largest.y * this->m_tiles.size(); size_t side = std::sqrt( area ) * padding; size = { side, side }; { @@ -63,64 +81,70 @@ void uf::Atlas::generate( const uf::Atlas::images_t& images, float padding ) { } } queue.Sort(); - this->m_atlas = BinPack2D::UniformCanvasArrayBuilder(size.x, size.y, 1).Build(); - bool success = this->m_atlas.Place( queue, remainder ); + internalAtlas = BinPack2D::UniformCanvasArrayBuilder(size.x, size.y, 1).Build(); + bool success = internalAtlas.Place( queue, remainder ); if ( success && remainder.Get().empty() ) break; // increase padding padding += 0.10f; } while ( --tries ); - this->m_image.loadFromBuffer( NULL, size, 8, 4 ); - this->m_atlas.CollectContent( stored ); - - auto& dstBuffer = this->m_image.getPixels(); - - for ( size_t i = 0; i < size.x * size.y * 4; i+=4 ) { - dstBuffer[i+0] = 0; - dstBuffer[i+1] = 0; - dstBuffer[i+2] = 0; - dstBuffer[i+3] = 0; - } + internalAtlas.CollectContent( stored ); + this->m_atlas.loadFromBuffer( NULL, size, 8, channels ); + auto& dstBuffer = this->m_atlas.getPixels(); + for ( size_t i = 0; i < size.x * size.y * channels; ++i ) dstBuffer[i] = 0; for ( auto& it : stored.Get() ) { - size_t index = it.content.index; - auto& image = images[index]; - auto& dim = image.getDimensions(); - auto channels = image.getChannels(); + auto& tile = this->m_tiles[it.content.hash]; + tile.coord = { it.coord.x, it.coord.y }; + tile.size = { it.size.w, it.size.h }; +/* + } + for ( auto pair : this->m_tiles ) { + auto& tile = pair.second; +*/ + auto& image = tile.image; auto& srcBuffer = image.getPixels(); + auto srcChannels = image.getChannels(); - for ( size_t y = 0; y < dim.y; ++y ) { - for ( size_t x = 0; x < dim.x; ++x ) { - size_t src = (y * dim.x * channels) + (x * channels); - size_t dst = ((y + it.coord.y) * size.x * 4) + ((x + it.coord.x) * 4); - for ( size_t i = 0; i < channels; ++i ) { + for ( size_t y = 0; y < tile.size.y; ++y ) { + for ( size_t x = 0; x < tile.size.x; ++x ) { + size_t src = (y * tile.size.x * srcChannels) + (x * srcChannels); + size_t dst = ((y + tile.coord.y) * size.x * channels) + ((x + tile.coord.x) * channels); + for ( size_t i = 0; i < srcChannels; ++i ) { dstBuffer[dst+i] = srcBuffer[src+i]; } } } } } -void uf::Atlas::clear() { - this->m_images.clear(); - this->m_image.clear(); - this->m_atlas = uf::Atlas::atlas_t{}; +bool uf::Atlas::generated() const { + return !this->m_atlas.getPixels().empty(); +} +void uf::Atlas::clear( bool full ) { + if ( !full ) { + for ( auto pair : this->m_tiles ) pair.second.image.clear(); + return; + } + this->m_tiles.clear(); + this->m_atlas.clear(); +} +pod::Vector2f uf::Atlas::mapUv( const pod::Vector2f& uv, const uf::Atlas::hash_t& hash ) { + auto& size = this->m_atlas.getDimensions(); + for ( auto pair : this->m_tiles ) { + auto& tile = pair.second; + if ( tile.identifier.hash != hash ) continue; + pod::Vector2ui coord = { uv.x * tile.size.x + tile.coord.x, uv.y * tile.size.y + tile.coord.y }; + return pod::Vector2f{ (float) coord.x / (float) size.x, (float) coord.y / (float) size.y }; + } + return uv; } pod::Vector2f uf::Atlas::mapUv( const pod::Vector2f& uv, size_t index ) { - BinPack2D::ContentAccumulator stored; - this->m_atlas.CollectContent( stored ); - auto& size = this->m_image.getDimensions(); - for ( auto& it : stored.Get() ) { - if ( it.content.index != index ) continue; - pod::Vector2ui dim = { it.size.w, it.size.h }; - pod::Vector2f nuv = uv; - if ( nuv.x > 1.0f ) nuv.x = std::fmod( nuv.x, 1.0f ); - if ( nuv.y > 1.0f ) nuv.y = std::fmod( nuv.y, 1.0f ); - - pod::Vector2ui coord = { uv.x * dim.x + it.coord.x, uv.y * dim.y + it.coord.y }; - nuv = { (float) coord.x / (float) size.x, (float) coord.y / (float) size.y }; - // nuv.y = 1.0f - nuv.y; - return nuv; + auto& size = this->m_atlas.getDimensions(); + for ( auto pair : this->m_tiles ) { + auto& tile = pair.second; + if ( tile.identifier.index != index ) continue; + pod::Vector2ui coord = { uv.x * tile.size.x + tile.coord.x, uv.y * tile.size.y + tile.coord.y }; + return pod::Vector2f{ (float) coord.x / (float) size.x, (float) coord.y / (float) size.y }; } - // std::cout << "Could not find requested index of " << index << std::endl; return uv; } pod::Vector3f uf::Atlas::mapUv( const pod::Vector3f& uv ) { @@ -128,174 +152,14 @@ pod::Vector3f uf::Atlas::mapUv( const pod::Vector3f& uv ) { return { nuv.x, nuv.y, uv.z }; } uf::Image& uf::Atlas::getAtlas() { - return this->m_image; + return this->m_atlas; } -uf::Atlas::images_t& uf::Atlas::getImages() { - return this->m_images; +const uf::Image& uf::Atlas::getAtlas() const { + return this->m_atlas; } -const uf::Atlas::images_t& uf::Atlas::getImages() const { - return this->m_images; +uf::Atlas::atlas_t& uf::Atlas::getImages() { + return this->m_tiles; } - - - - - - - - - -#include -#include - -uf::HashAtlas::hash_t uf::HashAtlas::addImage( const uf::Image& _image, bool regenerate ) { - auto hash = _image.getHash(); - if ( this->has( hash ) ) return hash; - - auto& image = *(this->m_images.emplace(hash, _image)).first; - if ( regenerate ) this->generate(); - - return hash; -} -uf::HashAtlas::hash_t uf::HashAtlas::addImage( uf::Image&& _image, bool regenerate ) { - auto hash = _image.getHash(); - if ( this->has( hash ) ) return hash; - - auto& image = *(this->m_images.emplace(hash, _image)).first; - if ( regenerate ) this->generate(); - - return hash; -} -uf::HashAtlas::hash_t uf::HashAtlas::addImage( const uint8_t* pointer, const pod::Vector2ui& size, std::size_t bpp, std::size_t channels, bool flip, bool regenerate ) { - uf::Image image; - image.loadFromBuffer( pointer, size, bpp, channels, flip ); - std::string hash = image.getHash(); - if ( this->has( hash ) ) return hash; - this->m_images.emplace( hash, std::move(image) ); - if ( regenerate ) this->generate(); - return hash; - -} -bool uf::HashAtlas::has( const uf::Image& image ) const { - return this->has( image.getHash() ); -} -bool uf::HashAtlas::has( const std::string& hash ) const { - return this->m_images.count(hash) > 0; -} -void uf::HashAtlas::generate( float padding ) { - return generate( this->m_images, padding ); -} -void uf::HashAtlas::generate( const uf::HashAtlas::images_t& images, float padding ) { - if ( images.empty() ) return; - // destroy atlas - this->m_image.clear(); - - BinPack2D::ContentAccumulator queue; - pod::Vector2ui size = {0,0}; - pod::Vector3ui largest = {0,0,0}; - size_t index = 0; - size_t area = 0; - for ( auto& pair : images ) { - auto hash = pair.first; - auto& dim = pair.second.getDimensions(); - queue += BinPack2D::Content({hash}, BinPack2D::Coord(), BinPack2D::Size(dim.x, dim.y), false ); - size += dim; - area += dim.x * dim.y; - if ( area >= largest.z ) { - largest.x = dim.x; - largest.y = dim.y; - } - } - size_t tries = 16; - BinPack2D::ContentAccumulator stored, remainder; - do { - { - // size_t area = largest.x * largest.y * images.size(); - size_t side = std::sqrt( area ) * padding; - size = { side, side }; - { - size.x--; - size.x |= size.x >> 1; - size.x |= size.x >> 2; - size.x |= size.x >> 4; - size.x |= size.x >> 8; - size.x |= size.x >> 16; - size.x++; - size.y--; - size.y |= size.y >> 1; - size.y |= size.y >> 2; - size.y |= size.y >> 4; - size.y |= size.y >> 8; - size.y |= size.y >> 16; - size.y++; - } - } - queue.Sort(); - this->m_atlas = BinPack2D::UniformCanvasArrayBuilder(size.x, size.y ,1).Build(); - bool success = this->m_atlas.Place( queue, remainder ); - if ( success && remainder.Get().empty() ) break; - // increase padding - padding += 0.10f; - } while ( --tries ); - this->m_image.loadFromBuffer( NULL, size, 8, 4 ); - this->m_atlas.CollectContent( stored ); - - auto& dstBuffer = this->m_image.getPixels(); - - for ( size_t i = 0; i < size.x * size.y * 4; i+=4 ) { - dstBuffer[i+0] = 0; - dstBuffer[i+1] = 0; - dstBuffer[i+2] = 0; - dstBuffer[i+3] = 0; - } - - for ( auto& it : stored.Get() ) { - auto& hash = it.content.hash; - auto& image = images.at(hash); - auto& dim = image.getDimensions(); - auto channels = image.getChannels(); - auto& srcBuffer = image.getPixels(); - - for ( size_t y = 0; y < dim.y; ++y ) { - for ( size_t x = 0; x < dim.x; ++x ) { - size_t src = (y * dim.x * channels) + (x * channels); - size_t dst = ((y + it.coord.y) * size.x * 4) + ((x + it.coord.x) * 4); - for ( size_t i = 0; i < channels; ++i ) { - dstBuffer[dst+i] = srcBuffer[src+i]; - } - } - } - } -} -void uf::HashAtlas::clear() { - this->m_images.clear(); - this->m_image.clear(); - this->m_atlas = uf::HashAtlas::atlas_t{}; -} -pod::Vector2f uf::HashAtlas::mapUv( const pod::Vector2f& uv, const uf::HashAtlas::hash_t& hash ) { - BinPack2D::ContentAccumulator stored; - this->m_atlas.CollectContent( stored ); - auto& size = this->m_image.getDimensions(); - for ( auto& it : stored.Get() ) { - if ( it.content.hash != hash ) continue; - pod::Vector2ui dim = { it.size.w, it.size.h }; - pod::Vector2f nuv = uv; - if ( nuv.x > 1.0f ) nuv.x = std::fmod( nuv.x, 1.0f ); - if ( nuv.y > 1.0f ) nuv.y = std::fmod( nuv.y, 1.0f ); - - pod::Vector2ui coord = { uv.x * dim.x + it.coord.x, uv.y * dim.y + it.coord.y }; - nuv = { (float) coord.x / (float) size.x, (float) coord.y / (float) size.y }; - nuv.y = 1.0f - nuv.y; - return nuv; - } - return uv; -} -uf::Image& uf::HashAtlas::getAtlas() { - return this->m_image; -} -uf::HashAtlas::images_t& uf::HashAtlas::getImages() { - return this->m_images; -} -const uf::HashAtlas::images_t& uf::HashAtlas::getImages() const { - return this->m_images; +const uf::Atlas::atlas_t& uf::Atlas::getImages() const { + return this->m_tiles; } \ No newline at end of file diff --git a/engine/src/utils/image/image.cpp b/engine/src/utils/image/image.cpp index b193254f..6ca06a4a 100644 --- a/engine/src/utils/image/image.cpp +++ b/engine/src/utils/image/image.cpp @@ -91,6 +91,7 @@ bool uf::Image::open( const std::string& _filename, bool flip ) { #if UF_ENV_DREAMCAST std::string dtex = uf::string::replace( filename, ".png", ".dtex" ); if ( uf::io::exists(dtex) ) { + UF_DEBUG_MSG("Loading dtex instead for: " << filename); filename = dtex; } #endif @@ -127,23 +128,36 @@ bool uf::Image::open( const std::string& _filename, bool flip ) { uint32_t expected = 2 * header.width * header.height; uint32_t ratio = (uint32_t) (((float) expected) / ((float) header.size)); bit_depth = 4; + this->m_format = format; if ( compressed ) { if ( twiddled ) { switch ( format ) { - case 0: this->m_format = mipmapped ? GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS : GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS; break; case 1: this->m_format = mipmapped ? GL_COMPRESSED_RGB_565_VQ_MIPMAP_TWID_KOS : GL_COMPRESSED_RGB_565_VQ_TWID_KOS; channels = 3; break; + case 0: this->m_format = mipmapped ? GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS : GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS; break; case 2: this->m_format = mipmapped ? GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_TWID_KOS : GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS; break; default: UF_EXCEPTION(filename << ": invalid texture format"); return false; } } else { switch ( format ) { - case 0: this->m_format = mipmapped ? GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_KOS : GL_COMPRESSED_ARGB_1555_VQ_KOS; break; case 1: this->m_format = mipmapped ? GL_COMPRESSED_RGB_565_VQ_MIPMAP_KOS : GL_COMPRESSED_RGB_565_VQ_KOS; channels = 3; break; + case 0: this->m_format = mipmapped ? GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_KOS : GL_COMPRESSED_ARGB_1555_VQ_KOS; break; case 2: this->m_format = mipmapped ? GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_KOS : GL_COMPRESSED_ARGB_4444_VQ_KOS; break; default: UF_EXCEPTION(filename << ": invalid texture format"); return false; } } } else { UF_EXCEPTION(filename << ": not a compressed texture"); return false; } + /* + UF_DEBUG_MSG("DTEX Header: " << header.id[0] << header.id[1] << header.id[2] << header.id[3] << " | " + << header.width << " x " << header.height << " | " + << twiddled << " | " + << compressed << " | " + << mipmapped << " | " + << strided << " | " + << header.size << " | " + << std::bitset<32>(format) << " | " + << std::bitset<32>(this->m_format) + ); + */ } else #endif { @@ -261,6 +275,7 @@ void uf::Image::copy( const uf::Image& copy ) { this->m_bpp = copy.m_bpp; this->m_channels = copy.m_channels; this->m_filename = copy.m_filename; + this->m_format = copy.m_format; } // D-tor uf::Image::~Image() { @@ -426,5 +441,6 @@ uf::Image& uf::Image::operator=( const uf::Image& copy ) { this->m_bpp = copy.m_bpp; this->m_channels = copy.m_channels; this->m_filename = copy.m_filename; + this->m_format = copy.m_format; return *this; } \ No newline at end of file diff --git a/engine/src/utils/mesh/grid.cpp b/engine/src/utils/mesh/grid.cpp index 4bdc2456..cbc14c9c 100644 --- a/engine/src/utils/mesh/grid.cpp +++ b/engine/src/utils/mesh/grid.cpp @@ -93,7 +93,7 @@ const pod::Vector3f& uf::MeshGrid::center() const { return this->m_center; } const pod::Vector3f& uf::MeshGrid::extent() const { return this->m_extent; } void uf::MeshGrid::insert( uint32_t i1, uint32_t i2, uint32_t i3, const pod::Vector3f& v1, const pod::Vector3f& v2, const pod::Vector3f& v3 ) { -#if 1 +#if 0 bool useStrongest = false; int32_t strongestNode = -1; pod::Collider::Manifold strongestManifold = {}; @@ -125,7 +125,7 @@ void uf::MeshGrid::insert( uint32_t i1, uint32_t i2, uint32_t i3, const pod::Vec node.indices.emplace_back(i3); } #endif -#if 0 +#if 1 auto center = centroid( v1, v2, v3 ); for ( size_t i = 0; i < this->m_nodes.size(); ++i ) { auto& node = this->m_nodes[i]; diff --git a/ext/behaviors/baking/behavior.cpp b/ext/behaviors/baking/behavior.cpp index 16d96da3..98531900 100644 --- a/ext/behaviors/baking/behavior.cpp +++ b/ext/behaviors/baking/behavior.cpp @@ -44,11 +44,11 @@ void ext::BakingBehavior::initialize( uf::Object& self ) { graphic.process = false; graphic.descriptor.cullMode = uf::renderer::enums::CullMode::NONE; - if ( graph.atlas ) { + if ( graph.atlas.generated() ) { for ( auto& texture : graph.textures ) { ++texture.storage.index; } - auto& image = *graph.images.emplace(graph.images.begin(), graph.atlas->getAtlas()); + auto& image = *graph.images.emplace(graph.images.begin(), graph.atlas.getAtlas()); auto& texture = *graph.textures.emplace(graph.textures.begin()); texture.name = "atlas"; texture.bind = true; diff --git a/ext/behaviors/light/behavior.cpp b/ext/behaviors/light/behavior.cpp index f82a3a72..ff5fa8c2 100644 --- a/ext/behaviors/light/behavior.cpp +++ b/ext/behaviors/light/behavior.cpp @@ -30,10 +30,17 @@ void ext::LightBehavior::initialize( uf::Object& self ) { if ( ++::roundRobin.current >= ::roundRobin.lights.size() ) ::roundRobin.current = 0; }); } - +/* + if ( !metadataJson["light"]["bias"]["shader"].is() ) { + metadataJson["light"]["bias"]["shader"] = 0.000000005f; + } +*/ if ( !metadataJson["light"]["bias"]["constant"].is() ) { metadataJson["light"]["bias"]["constant"] = 0.00005f; } + if ( !metadataJson["light"]["type"].is() ) { + metadataJson["light"]["type"] = "point"; + } if ( !ext::json::isArray( metadataJson["light"]["color"] ) ) { metadataJson["light"]["color"][0] = 1; //metadataJson["light"]["color"]["random"].as() ? (rand() % 100) / 100.0 : 1; metadataJson["light"]["color"][1] = 1; //metadataJson["light"]["color"]["random"].as() ? (rand() % 100) / 100.0 : 1; @@ -70,7 +77,6 @@ void ext::LightBehavior::initialize( uf::Object& self ) { renderMode.metadata["type"] = "depth"; renderMode.metadata["depth bias"] = metadataJson["light"]["bias"]; renderMode.metadata["renderMode"] = metadataJson["renderMode"]; - // std::cout << this->getName() << ": " << renderMode.metadata["renderMode"] << std::endl; if ( metadataJson["light"]["type"].as() == "point" ) { metadataJson["light"]["fov"] = 90.0f; @@ -88,7 +94,7 @@ void ext::LightBehavior::initialize( uf::Object& self ) { auto& cameraSize = camera.getSize(); renderMode.width = cameraSize.x; renderMode.height = cameraSize.y; - + // UF_DEBUG_MSG(this->getName() << ": " << renderMode.metadata << " | " << metadataJson["light"]); } metadata.serialize = [&](){ @@ -100,8 +106,8 @@ void ext::LightBehavior::initialize( uf::Object& self ) { metadataJson["light"]["external update"] = metadata.renderer.external; metadataJson["system"]["renderer"]["timer"] = metadata.renderer.limiter; switch ( metadata.type ) { - case 0: metadataJson["light"]["type"] = ""; break; - case 1: metadataJson["light"]["type"] = "point"; break; + case 0: metadataJson["light"]["type"] = "point"; break; + case 1: metadataJson["light"]["type"] = "spot"; break; case 2: metadataJson["light"]["type"] = "spot"; break; } }; @@ -118,8 +124,8 @@ void ext::LightBehavior::initialize( uf::Object& self ) { metadata.type = metadataJson["light"]["type"].as(); } else if ( metadataJson["light"]["type"].is() ) { std::string lightType = metadataJson["light"]["type"].as(); - if ( lightType == "point" ) metadata.type = 1; - else if ( lightType == "spot" ) metadata.type = 2; + if ( lightType == "point" ) metadata.type = 0; + else if ( lightType == "spot" ) metadata.type = 1; } }; this->addHook( "object:UpdateMetadata.%UID%", metadata.deserialize); @@ -148,8 +154,8 @@ void ext::LightBehavior::tick( uf::Object& self ) { metadata.type = metadataJson["light"]["type"].as(); } else if ( metadataJson["light"]["type"].is() ) { std::string lightType = metadataJson["light"]["type"].as(); - if ( lightType == "point" ) metadata.type = 1; - else if ( lightType == "spot" ) metadata.type = 2; + if ( lightType == "point" ) metadata.type = 0; + else if ( lightType == "spot" ) metadata.type = 1; } } #endif @@ -217,7 +223,7 @@ void ext::LightBehavior::tick( uf::Object& self ) { if ( !metadata.renderer.external ) { auto& camera = this->getComponent(); // omni light - if ( metadata.shadows && metadata.type == 1 ) { + if ( metadata.shadows && metadata.type == 0 ) { auto transform = camera.getTransform(); std::vector> rotations = { uf::quaternion::axisAngle( { 0, 1, 0 }, 0 * 1.57079633 ), diff --git a/ext/gui/behavior.cpp b/ext/gui/behavior.cpp index 6e489de4..0d4c5073 100644 --- a/ext/gui/behavior.cpp +++ b/ext/gui/behavior.cpp @@ -38,31 +38,48 @@ namespace { std::unordered_map> cache; } glyphs; #endif - -#if UF_USE_OPENGL - std::string defaultRenderMode = ""; -#else std::string defaultRenderMode = "Gui"; -#endif uf::Serializer defaultSettings; + + std::vector metadataKeys = { + "alpha", + "color", + "depth", + "font", + "only model", + "projection", + "scale", + "sdf", + "shader", + "shadowbox", + "size", + "spread", + "string", + "stroke", + "uv", + "weight", + "world", + }; } -/* -ext::Gui::Gui(){ - this->addBehavior(); -} -*/ std::vector ext::Gui::generateGlyphs( const std::string& _string ) { std::vector gs; #if UF_USE_FREETYPE uf::Object& gui = *this; std::string string = _string; - uf::Serializer& metadata = gui.getComponent(); - std::string font = uf::io::root+"/fonts/" + metadata["text settings"]["font"].as(); + auto& metadata = gui.getComponent(); + auto& metadataGlyph = gui.getComponent(); + auto& metadataJson = gui.getComponent(); + + metadata.deserialize(); + metadataGlyph.deserialize(); + +// std::string font = uf::io::root+"/fonts/" + metadataJson["text settings"]["font"].as(); + std::string font = uf::io::root+"/fonts/" + metadataGlyph.font; if ( ::glyphs.cache[font].empty() ) { ext::freetype::initialize( ::glyphs.glyph, font ); } if ( string == "" ) { - string = metadata["text settings"]["string"].as(); + string = metadataGlyph.string; } pod::Transform<>& transform = gui.getComponent>(); struct { @@ -97,17 +114,9 @@ std::vector ext::Gui::generateGlyphs( const std::string& _string } colors; } stat; - float scale = metadata["text settings"]["scale"].as(); - - { - pod::Vector3f color = { - metadata["text settings"]["color"][0].as(), - metadata["text settings"]["color"][1].as(), - metadata["text settings"]["color"][2].as(), - }; - stat.colors.container.push_back(color); - } - + float scale = metadataGlyph.scale; + pod::Vector3f color = metadata.color; + stat.colors.container.push_back(color); unsigned long COLORCONTROL = 0x7F; { @@ -152,20 +161,22 @@ std::vector ext::Gui::generateGlyphs( const std::string& _string unsigned long c = *it; if ( c == '\n' ) continue; if ( c == '\t' ) continue; if ( c == 0x01 ) continue; std::string key = ""; { key += std::to_string(c) + ";"; - key += metadata["text settings"]["padding"][0].as() + ","; - key += metadata["text settings"]["padding"][1].as() + ";"; - key += metadata["text settings"]["spread"].as() + ";"; - key += metadata["text settings"]["size"].as() + ";"; - key += metadata["text settings"]["font"].as() + ";"; - key += metadata["text settings"]["sdf"].as(); + key += std::to_string(metadataGlyph.padding[0]) + ","; + key += std::to_string(metadataGlyph.padding[1]) + ";"; + key += std::to_string(metadataGlyph.spread) + ";"; + key += std::to_string(metadataGlyph.size) + ";"; + key += metadataGlyph.font + ";"; + key += std::to_string(metadataGlyph.sdf); } uf::Glyph& glyph = ::glyphs.cache[font][key]; if ( !glyph.generated() ) { - glyph.setPadding( { metadata["text settings"]["padding"][0].as(), metadata["text settings"]["padding"][1].as() } ); - glyph.setSpread( metadata["text settings"]["spread"].as() ); - if ( metadata["text settings"]["sdf"].as() ) glyph.useSdf(true); - glyph.generate( ::glyphs.glyph, c, metadata["text settings"]["size"].as() ); + glyph.setPadding( { metadataGlyph.padding[0], metadataGlyph.padding[1] } ); + glyph.setSpread( metadataGlyph.spread ); + #if UF_USE_VULKAN + if ( metadataGlyph.sdf ) glyph.useSdf(true); + #endif + glyph.generate( ::glyphs.glyph, c, metadataGlyph.size ); } stat.biggest.x = std::max( (float) stat.biggest.x, (float) glyph.getSize().x); @@ -201,12 +212,12 @@ std::vector ext::Gui::generateGlyphs( const std::string& _string } std::string key = ""; { key += std::to_string(c) + ";"; - key += metadata["text settings"]["padding"][0].as() + ","; - key += metadata["text settings"]["padding"][1].as() + ";"; - key += metadata["text settings"]["spread"].as() + ";"; - key += metadata["text settings"]["size"].as() + ";"; - key += metadata["text settings"]["font"].as() + ";"; - key += metadata["text settings"]["sdf"].as(); + key += std::to_string(metadataGlyph.padding[0]) + ","; + key += std::to_string(metadataGlyph.padding[1]) + ";"; + key += std::to_string(metadataGlyph.spread) + ";"; + key += std::to_string(metadataGlyph.size) + ";"; + key += metadataGlyph.font + ";"; + key += std::to_string(metadataGlyph.sdf); } uf::Glyph& glyph = ::glyphs.cache[font][key]; pod::GlyphBox g; @@ -220,17 +231,17 @@ std::vector ext::Gui::generateGlyphs( const std::string& _string stat.cursor.x += (glyph.getAdvance().x); } - stat.origin.x = ( !metadata["text settings"]["world"].as() && transform.position.x != (int) transform.position.x ) ? transform.position.x * ext::gui::size.current.x : transform.position.x; - stat.origin.y = ( !metadata["text settings"]["world"].as() && transform.position.y != (int) transform.position.y ) ? transform.position.y * ext::gui::size.current.y : transform.position.y; - - - if ( ext::json::isArray( metadata["text settings"]["origin"] ) ) { - stat.origin.x = metadata["text settings"]["origin"][0].as(); - stat.origin.y = metadata["text settings"]["origin"][1].as(); + stat.origin.x = ( !metadata.world && transform.position.x != (int) transform.position.x ) ? transform.position.x * ext::gui::size.current.x : transform.position.x; + stat.origin.y = ( !metadata.world && transform.position.y != (int) transform.position.y ) ? transform.position.y * ext::gui::size.current.y : transform.position.y; + /* + if ( ext::json::isArray( metadataJson["text settings"]["origin"] ) ) { + stat.origin.x = metadataJson["text settings"]["origin"][0].as(); + stat.origin.y = metadataJson["text settings"]["origin"][1].as(); } - else if ( metadata["text settings"]["origin"] == "top" ) stat.origin.y = ext::gui::size.current.y - stat.origin.y - stat.biggest.y;// else stat.origin.y = stat.origin.y; - if ( metadata["text settings"]["align"] == "right" ) stat.origin.x = ext::gui::size.current.x - stat.origin.x - stat.box.w;// else stat.origin.x = stat.origin.x; - else if ( metadata["text settings"]["align"] == "center" ) + */ + if ( metadataGlyph.origin == "top" ) stat.origin.y = ext::gui::size.current.y - stat.origin.y - stat.biggest.y;// else stat.origin.y = stat.origin.y; + if ( metadataGlyph.align == "right" ) stat.origin.x = ext::gui::size.current.x - stat.origin.x - stat.box.w;// else stat.origin.x = stat.origin.x; + else if ( metadataGlyph.align == "center" ) stat.origin.x -= stat.box.w * 0.5f; } @@ -239,7 +250,7 @@ std::vector ext::Gui::generateGlyphs( const std::string& _string stat.cursor.y = stat.biggest.y; for ( auto it = str.begin(); it != str.end(); ++it ) { unsigned long c = *it; if ( c == '\n' ) { - if ( metadata["text settings"]["direction"] == "down" ) stat.cursor.y -= stat.biggest.y; else stat.cursor.y += stat.biggest.y; + if ( metadataGlyph.direction == "down" ) stat.cursor.y -= stat.biggest.y; else stat.cursor.y += stat.biggest.y; stat.cursor.x = 0; continue; } else if ( c == '\t' ) { @@ -259,12 +270,12 @@ std::vector ext::Gui::generateGlyphs( const std::string& _string } std::string key = ""; { key += std::to_string(c) + ";"; - key += metadata["text settings"]["padding"][0].as() + ","; - key += metadata["text settings"]["padding"][1].as() + ";"; - key += metadata["text settings"]["spread"].as() + ";"; - key += metadata["text settings"]["size"].as() + ";"; - key += metadata["text settings"]["font"].as() + ";"; - key += metadata["text settings"]["sdf"].as(); + key += std::to_string(metadataGlyph.padding[0]) + ","; + key += std::to_string(metadataGlyph.padding[1]) + ";"; + key += std::to_string(metadataGlyph.spread) + ";"; + key += std::to_string(metadataGlyph.size) + ";"; + key += metadataGlyph.font + ";"; + key += std::to_string(metadataGlyph.sdf); } uf::Glyph& glyph = ::glyphs.cache[font][key]; @@ -283,11 +294,7 @@ std::vector ext::Gui::generateGlyphs( const std::string& _string g.color = stat.colors.container.at(stat.colors.index); } else { std::cout << "Invalid color index `" << stat.colors.index << "` for string: " << string << ": (" << stat.colors.container.size() << ")" << std::endl; - g.color = { - metadata["text settings"]["color"][0].as(), - metadata["text settings"]["color"][1].as(), - metadata["text settings"]["color"][2].as(), - }; + g.color = metadata.color; } gs.push_back(g); } @@ -295,131 +302,95 @@ std::vector ext::Gui::generateGlyphs( const std::string& _string return gs; } -void ext::Gui::load( const uf::Image& _image ) { +void ext::Gui::load( const uf::Image& image ) { auto& scene = uf::scene::getCurrentScene(); - +/* auto& image = this->getComponent(); - // image = uf::Image( _image ); image.copy( _image ); - auto& metadata = this->getComponent(); - metadata["size"][0] = image.getDimensions().x; - metadata["size"][1] = image.getDimensions().y; +*/ + auto& metadata = this->getComponent(); + auto& metadataGlyph = this->getComponent(); + auto& metadataJson = this->getComponent(); + metadata.size = image.getDimensions(); auto& graphic = this->getComponent(); auto& texture = graphic.material.textures.emplace_back(); texture.loadFromImage( image ); -/* - { - pod::Transform<>& transform = gui.getComponent>(); - uf::GuiMesh& mesh = gui.getComponent(); - auto& texture = graphic.material.textures.front(); - pod::Vector2f textureSize = { - metadata["size"][0].as(), - metadata["size"][1].as() - }; - - if ( metadata["scaling"].as() == "fixed" ) { - transform.scale = pod::Vector3{ (float) textureSize.x / ext::gui::size.current.x, (float) textureSize.y / ext::gui::size.current.y, 1 }; - } else if ( metadata["scaling"].as() == "fixed-1080p" ) { - transform.scale = pod::Vector3{ (float) textureSize.x / 1920, (float) textureSize.y / 1080, 1 }; - } - } -*/ - - auto& mesh = this->getComponent(); + auto& mesh = this->getComponent(); auto& transform = this->getComponent>(); mesh.vertices = { - { {1.0f, -1.0f}, {1.0f, 0.0f}, }, - { {-1.0f, -1.0f}, {0.0f, 0.0f}, }, - { {-1.0f, 1.0f}, {0.0f, 1.0f}, }, + { pod::Vector3f{ 1.0f, -1.0f, 0.0f}, pod::Vector2f{1.0f, 0.0f}, metadata.color }, + { pod::Vector3f{-1.0f, -1.0f, 0.0f}, pod::Vector2f{0.0f, 0.0f}, metadata.color }, + { pod::Vector3f{-1.0f, 1.0f, 0.0f}, pod::Vector2f{0.0f, 1.0f}, metadata.color }, - { {-1.0f, 1.0f}, {0.0f, 1.0f}, }, - { {1.0f, 1.0f}, {1.0f, 1.0f}, }, - { {1.0f, -1.0f}, {1.0f, 0.0f}, }, - /* - { {-1.0f, 1.0f}, {0.0f, 0.0f}, }, - { {-1.0f, -1.0f}, {0.0f, 1.0f}, }, - { {1.0f, -1.0f}, {1.0f, 1.0f}, }, - - { {-1.0f, 1.0f}, {0.0f, 0.0f}, }, - { {1.0f, -1.0f}, {1.0f, 1.0f}, }, - { {1.0f, 1.0f}, {1.0f, 0.0f}, } - */ + { pod::Vector3f{-1.0f, 1.0f, 0.0f}, pod::Vector2f{0.0f, 1.0f}, metadata.color }, + { pod::Vector3f{ 1.0f, 1.0f, 0.0f}, pod::Vector2f{1.0f, 1.0f}, metadata.color }, + { pod::Vector3f{ 1.0f, -1.0f, 0.0f}, pod::Vector2f{1.0f, 0.0f}, metadata.color }, }; pod::Vector2f raidou = { 1, 1 }; bool modified = false; - if ( metadata["mode"].as() == "flat" ) { - if ( ext::json::isNull(metadata["projection"]) ) metadata["projection"] = false; - if ( ext::json::isNull(metadata["flip uv"]) ) metadata["flip uv"] = true; - if ( ext::json::isNull(metadata["front face"]) ) metadata["front face"] = "ccw"; + if ( metadataJson["mode"].as() == "flat" ) { + if ( ext::json::isNull(metadataJson["projection"]) ) metadataJson["projection"] = false; + if ( ext::json::isNull(metadataJson["flip uv"]) ) metadataJson["flip uv"] = true; + if ( ext::json::isNull(metadataJson["front face"]) ) metadataJson["front face"] = "ccw"; + #if UF_USE_OPENGL + metadataJson["cull mode"] = "back"; + // metadataJson["depth test"]["test"] = false; + // metadataJson["depth test"]["write"] = true; + // if ( metadataJson["flip uv"].is() ) metadataJson["flip uv"] = !metadataJson["flip uv"].as(); + #endif } else { - if ( ext::json::isNull(metadata["projection"]) ) metadata["projection"] = true; - if ( ext::json::isNull(metadata["flip uv"]) ) metadata["flip uv"] = false; - if ( ext::json::isNull(metadata["front face"]) ) metadata["front face"] = "cw"; + if ( ext::json::isNull(metadataJson["projection"]) ) metadataJson["projection"] = true; + if ( ext::json::isNull(metadataJson["flip uv"]) ) metadataJson["flip uv"] = false; + if ( ext::json::isNull(metadataJson["front face"]) ) metadataJson["front face"] = "cw"; } - graphic.descriptor.parse( metadata ); + metadataJson["cull mode"] = "none"; + graphic.descriptor.parse( metadataJson ); - if ( metadata["flip uv"].as() ) { - for ( auto& v : mesh.vertices ) { - v.uv.y = 1 - v.uv.y; - } + if ( metadataJson["flip uv"].as() ) { + for ( auto& v : mesh.vertices ) v.uv.y = 1 - v.uv.y; } - if ( metadata["scaling"].is() ) { - std::string mode = metadata["scaling"].as(); + if ( metadata.depth != 0.0f ) + for ( auto& v : mesh.vertices ) v.position.z = metadata.depth; + if ( metadataJson["scaling"].is() ) { + std::string mode = metadataJson["scaling"].as(); if ( mode == "mesh" ) { // raidou.x = (float) image.getDimensions().x / image.getDimensions().y; raidou.y = (float) image.getDimensions().y / image.getDimensions().x; modified = true; } - } else if ( ext::json::isArray(metadata["scaling"]) ) { - raidou.x = metadata["scaling"][0].as(); - raidou.y = metadata["scaling"][1].as(); + } else if ( ext::json::isArray(metadataJson["scaling"]) ) { + raidou = uf::vector::decode( metadataJson["scaling"], raidou ); modified = true; } if ( modified ) { transform.scale.x = raidou.x; transform.scale.y = raidou.y; } -/* - for ( auto& vertex : mesh.vertices ) { - vertex.position.x *= raidou.x; - vertex.position.y *= raidou.y; - } - - transform.scale.x = raidou.x; - transform.scale.y = raidou.y; -*/ -/* - if ( !metadata["gui layer"].as() ) { - graphic.initialize( ::defaultRenderMode ); - } else { + if ( metadataJson["layer"].is() ) { + graphic.initialize( metadataJson["layer"].as() ); + } else if ( !ext::json::isNull( metadataJson["gui layer"] ) && !metadataJson["gui layer"].as() ) { graphic.initialize(); - } -*/ - if ( metadata["layer"].is() ) { - graphic.initialize( metadata["layer"].as() ); - } else if ( !ext::json::isNull( metadata["gui layer"] ) && !metadata["gui layer"].as() ) { - graphic.initialize(); - } else if ( metadata["gui layer"].is() ) { - graphic.initialize( metadata["gui layer"].as() ); + } else if ( metadataJson["gui layer"].is() ) { + graphic.initialize( metadataJson["gui layer"].as() ); } else { graphic.initialize( ::defaultRenderMode ); } graphic.initializeMesh( mesh ); struct { - std::string vertex = uf::io::root+"/shaders/gui/vert.spv"; - std::string fragment = uf::io::root+"/shaders/gui/frag.spv"; + std::string vertex = uf::io::root+"/shaders/gui/base.vert.spv"; + std::string fragment = uf::io::root+"/shaders/gui/base.frag.spv"; } filenames; std::string suffix = ""; { std::string _ = scene.getComponent()["shaders"]["gui"]["suffix"].as(); if ( _ != "" ) suffix = _ + "."; } - if ( metadata["shaders"]["vertex"].is() ) filenames.vertex = metadata["shaders"]["vertex"].as(); - if ( metadata["shaders"]["fragment"].is() ) filenames.fragment = metadata["shaders"]["fragment"].as(); - else if ( suffix != "" ) filenames.fragment = uf::io::root+"/shaders/gui/"+suffix+"frag.spv"; + if ( metadataJson["shaders"]["vertex"].is() ) filenames.vertex = metadataJson["shaders"]["vertex"].as(); + if ( metadataJson["shaders"]["fragment"].is() ) filenames.fragment = metadataJson["shaders"]["fragment"].as(); + else if ( suffix != "" ) filenames.fragment = uf::io::root+"/shaders/gui/"+suffix+"base.frag.spv"; graphic.material.initializeShaders({ {filenames.vertex, uf::renderer::enums::Shader::VERTEX}, @@ -444,32 +415,57 @@ UF_OBJECT_REGISTER_BEGIN(ext::Gui) UF_OBJECT_REGISTER_END() #define this (&self) void ext::GuiBehavior::initialize( uf::Object& self ) { - auto& metadata = this->getComponent(); -#if UF_USE_FREETYPE - this->addHook( "glyph:Load.%UID%", [&](ext::json::Value& json){ - unsigned long c = json["glyph"].as(); - std::string font = uf::io::root+"/fonts/" + metadata["text settings"]["font"].as(); - std::string key = ""; { - key += std::to_string(c) + ";"; - key += metadata["text settings"]["padding"][0].as() + ","; - key += metadata["text settings"]["padding"][1].as() + ";"; - key += metadata["text settings"]["spread"].as() + ";"; - key += metadata["text settings"]["size"].as() + ";"; - key += metadata["text settings"]["font"].as() + ";"; - key += metadata["text settings"]["sdf"].as(); + auto& metadata = this->getComponent(); + auto& metadataJson = this->getComponent(); + + metadata.serialize = [&]() { + metadataJson["gui"]["color"] = uf::vector::encode( metadata.color ); + metadataJson["gui"]["world"] = metadata.world; + if ( metadata.mode == 1 ) metadataJson["gui"]["only model"] = true; + else if ( metadata.mode == 2 ) metadataJson["gui"]["world"] = true; + else if ( metadata.mode == 3 ) metadataJson["gui"]["projection"] = true; + metadataJson["box"]["min"] = uf::vector::encode( metadata.box.min ); + metadataJson["box"]["max"] = uf::vector::encode( metadata.box.max ); + metadataJson["gui"]["clicked"] = metadata.clicked; + metadataJson["gui"]["hovered"] = metadata.hovered; + metadataJson["gui"]["uv"] = uf::vector::encode( metadata.uv ); + metadataJson["gui"]["shader"] = metadata.shader; + metadataJson["gui"]["depth"] = metadata.depth; + metadataJson["gui"]["alpha"] = metadata.alpha; + + for ( auto& key : ::metadataKeys ) { + if ( !ext::json::isNull( metadataJson[key] ) ) + metadataJson["gui"][key] = metadataJson[key]; + if ( !ext::json::isNull( metadataJson["text settings"][key] ) ) + metadataJson["gui"][key] = metadataJson["text settings"][key]; + } + }; + metadata.deserialize = [&]() { + for ( auto& key : ::metadataKeys ) { + if ( !ext::json::isNull( metadataJson[key] ) ) + metadataJson["gui"][key] = metadataJson[key]; + if ( !ext::json::isNull( metadataJson["text settings"][key] ) ) + metadataJson["gui"][key] = metadataJson["text settings"][key]; } - uf::Glyph& glyph = ::glyphs.cache[font][key]; - uf::Image image; { - const uint8_t* buffer = glyph.getBuffer(); - uf::Image::container_t pixels; - std::size_t len = glyph.getSize().x * glyph.getSize().y; - pixels.insert( pixels.end(), buffer, buffer + len ); - image.loadFromBuffer( pixels, glyph.getSize(), 8, 1, true ); - } - this->as().load( image ); - }); -#endif + metadata.color = uf::vector::decode( metadataJson["gui"]["color"], metadata.color ); + metadata.world = metadataJson["gui"]["world"].as(); + if ( metadataJson["gui"]["only model"].as() ) metadata.mode = 1; + else if ( metadataJson["gui"]["world"].as() ) metadata.mode = 2; + else if ( metadataJson["gui"]["projection"].as() ) metadata.mode = 3; + metadata.box.min = uf::vector::decode( metadataJson["box"]["min"], metadata.box.min ); + metadata.box.max = uf::vector::decode( metadataJson["box"]["max"], metadata.box.max ); + metadata.clicked = metadataJson["gui"]["clicked"].as(); + metadata.hovered = metadataJson["gui"]["hovered"].as(); + metadata.uv = uf::vector::decode( metadataJson["gui"]["uv"], metadata.uv ); + metadata.shader = metadataJson["gui"]["shader"].as(); + metadata.depth = metadataJson["gui"]["depth"].as(); + metadata.alpha = metadataJson["gui"]["alpha"].as(); + if ( metadataJson["gui"]["alpha"].is() ) metadata.color[3] *= metadata.alpha; + }; + this->addHook( "object:UpdateMetadata.%UID%", metadata.deserialize); + metadata.deserialize(); + this->addHook( "asset:Load.%UID%", [&](ext::json::Value& json){ std::string filename = json["filename"].as(); std::string category = json["category"].as(); @@ -479,51 +475,25 @@ void ext::GuiBehavior::initialize( uf::Object& self ) { uf::Scene& scene = uf::scene::getCurrentScene(); uf::Asset& assetLoader = scene.getComponent(); - const uf::Image* imagePointer = NULL; if ( !assetLoader.has(filename) ) return; - imagePointer = &assetLoader.get(filename); - if ( !imagePointer ) return; - // uf::Image image = *imagePointer; - this->as().load( *imagePointer ); - }); - this->addHook( "window:Resized", [&](ext::json::Value& json){ - if ( !this->hasComponent() ) return; - - pod::Vector2ui size; { - size.x = json["window"]["size"]["x"].as(); - size.y = json["window"]["size"]["y"].as(); - } - pod::Transform<>& transform = this->getComponent>(); - - /* - pod::Vector2f textureSize = { - metadata["size"][0].as(), - metadata["size"][1].as() - }; - if ( ext::json::isObject( metadata["text settings"] ) ) { - } else if ( metadata["scaling"].as() == "fixed" ) { - transform.scale = pod::Vector3{ (float) textureSize.x / size.x, (float) textureSize.y / size.y, 1 }; - } else if ( metadata["scaling"].as() == "fixed-1080p" ) { - transform.scale = pod::Vector3{ (float) textureSize.x / 1920, (float) textureSize.y / 1080, 1 }; - } - */ - } ); - - if ( metadata["system"]["clickable"].as() ) { + auto& image = assetLoader.get(filename); + this->as().load( image ); + }); + if ( metadataJson["system"]["clickable"].as() ) { uf::Timer clickTimer(false); - // clickTimer.start( uf::Time<>(-1000000) ); + clickTimer.start( uf::Time<>(-1000000) ); if ( !clickTimer.running() ) clickTimer.start(); this->addHook( "gui:Clicked.%UID%", [&](ext::json::Value& json){ - if ( ext::json::isObject( metadata["events"]["click"] ) ) { - uf::Serializer event = metadata["events"]["click"]; - metadata["events"]["click"] = ext::json::array(); //Json::arrayValue; - metadata["events"]["click"][0] = event; - } else if ( !ext::json::isArray( metadata["events"]["click"] ) ) { + 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().callHook("gui:Clicked.%UID%", json); return; } - for ( int i = 0; i < metadata["events"]["click"].size(); ++i ) { - uf::Serializer event = metadata["events"]["click"][i]; + for ( int i = 0; i < metadataJson["events"]["click"].size(); ++i ) { + uf::Serializer event = metadataJson["events"]["click"][i]; uf::Serializer payload = event["payload"]; if ( event["delay"].is() ) { this->queueHook(event["name"].as(), payload, event["delay"].as()); @@ -533,11 +503,8 @@ void ext::GuiBehavior::initialize( uf::Object& self ) { } }); this->addHook( "window:Mouse.Click", [&](ext::json::Value& json){ - uf::Serializer& metadata = this->getComponent(); - - if ( metadata["world"].as() ) return; - if ( ext::json::isNull( metadata["box"] ) ) return; - + if ( metadata.world ) return; + if ( !metadata.box.min && !metadata.box.max ) return; bool down = json["mouse"]["state"].as() == "Down"; bool clicked = false; if ( down ) { @@ -560,34 +527,30 @@ void ext::GuiBehavior::initialize( uf::Object& self ) { x = json["mouse"]["position"]["x"].as(); y = json["mouse"]["position"]["y"].as(); } - - pod::Vector2f min = { metadata["box"]["min"]["x"].as(), metadata["box"]["min"]["y"].as() }; - pod::Vector2f max = { metadata["box"]["max"]["x"].as(), metadata["box"]["max"]["y"].as() }; - clicked = ( min.x <= x && min.y <= y && max.x >= x && max.y >= y ); + clicked = ( metadata.box.min.x <= x && metadata.box.min.y <= y && metadata.box.max.x >= x && metadata.box.max.y >= y ); } } - metadata["clicked"] = clicked; - if ( clicked ) { - this->callHook("gui:Clicked.%UID%", json); - } + metadata.clicked = clicked; + metadataJson["clicked"] = clicked; + if ( clicked ) this->callHook("gui:Clicked.%UID%", json); this->callHook("gui:Mouse.Clicked.%UID%", json); } ); } - if ( metadata["system"]["hoverable"].as() ) { + if ( metadataJson["system"]["hoverable"].as() ) { uf::Timer hoverTimer(false); hoverTimer.start( uf::Time<>(-1000000) ); this->addHook( "gui:Hovered.%UID%", [&](ext::json::Value& json){ - if ( ext::json::isObject( metadata["events"]["hover"] ) ) { - uf::Serializer event = metadata["events"]["hover"]; - metadata["events"]["hover"] = ext::json::array(); //Json::arrayValue; - metadata["events"]["hover"][0] = event; - } else if ( !ext::json::isArray( metadata["events"]["hover"] ) ) { + if ( ext::json::isObject( metadataJson["events"]["hover"] ) ) { + uf::Serializer event = metadataJson["events"]["hover"]; + metadataJson["events"]["hover"] = ext::json::array(); //Json::arrayValue; + metadataJson["events"]["hover"][0] = event; + } else if ( !ext::json::isArray( metadataJson["events"]["hover"] ) ) { this->getParent().as().callHook("gui:Clicked.%UID%", json); return; } - for ( int i = 0; i < metadata["events"]["hover"].size(); ++i ) { - uf::Serializer event = metadata["events"]["hover"][i]; + for ( int i = 0; i < metadataJson["events"]["hover"].size(); ++i ) { + uf::Serializer event = metadataJson["events"]["hover"][i]; uf::Serializer payload = event["payload"]; float delay = event["delay"].as(); if ( event["delay"].is() ) { @@ -600,10 +563,10 @@ void ext::GuiBehavior::initialize( uf::Object& self ) { }); this->addHook( "window:Mouse.Moved", [&](ext::json::Value& json){ if ( this->getUid() == 0 ) return; - if ( !this->hasComponent() ) return; - uf::Serializer& metadata = this->getComponent(); - if ( metadata["world"].as() ) return; - if ( ext::json::isNull( metadata["box"] ) ) return; + if ( !this->hasComponent() ) return; + + if ( metadata.world ) return; + if ( !metadata.box.min && !metadata.box.max ) return; bool down = json["mouse"]["state"].as() == "Down"; bool clicked = false; @@ -620,11 +583,10 @@ void ext::GuiBehavior::initialize( uf::Object& self ) { float x = click.x; float y = click.y; - pod::Vector2f min = { metadata["box"]["min"]["x"].as(), metadata["box"]["min"]["y"].as() }; - pod::Vector2f max = { metadata["box"]["max"]["x"].as(), metadata["box"]["max"]["y"].as() }; - clicked = ( min.x <= x && min.y <= y && max.x >= x && max.y >= y ); + clicked = ( metadata.box.min.x <= x && metadata.box.min.y <= y && metadata.box.max.x >= x && metadata.box.max.y >= y ); } - metadata["hovered"] = clicked; + metadata.hovered = clicked; + metadataJson["hovered"] = clicked; if ( clicked && hoverTimer.elapsed().asDouble() >= 1 ) { hoverTimer.reset(); @@ -633,53 +595,122 @@ void ext::GuiBehavior::initialize( uf::Object& self ) { this->callHook("gui:Mouse.Moved.%UID%", json); } ); } - if ( metadata["text settings"]["string"].is() ) { - if ( ext::json::isNull( ::defaultSettings["metadata"] ) ) { - ::defaultSettings.readFromFile(uf::io::root+"/entities/gui/text/string.json"); - } - for ( auto it = ::defaultSettings["metadata"]["text settings"].begin(); it != ::defaultSettings["metadata"]["text settings"].end(); ++it ) { - std::string key = it.key(); - if ( ext::json::isNull( metadata["text settings"][key] ) ) { - metadata["text settings"][key] = ::defaultSettings["metadata"]["text settings"][key]; - } - } +#if UF_USE_FREETYPE + if ( metadataJson["text settings"]["string"].is() ) { + if ( ext::json::isNull( ::defaultSettings["metadata"] ) ) ::defaultSettings.readFromFile(uf::io::root+"/entities/gui/text/string.json"); - #if UF_USE_FREETYPE - if ( false ) { - uf::Serializer payload; - payload["first"] = true; - payload["string"] = metadata["text settings"]["string"]; - this->callHook("gui:UpdateString.%UID%", payload); - } else { + ext::json::forEach(::defaultSettings["metadata"]["text settings"], [&]( const std::string& key, ext::json::Value& value ){ + if ( ext::json::isNull( metadataJson["text settings"][key] ) ) + metadataJson["text settings"][key] = value; + }); + + auto& metadataGlyph = this->getComponent(); + metadataGlyph.serialize = [&]() { + metadataJson["text settings"]["font"] = metadataGlyph.font; + metadataJson["text settings"]["string"] = metadataGlyph.string; + + metadataJson["text settings"]["scale"] = metadataGlyph.scale; + metadataJson["text settings"]["padding"] = uf::vector::encode( metadataGlyph.padding ); + metadataJson["text settings"]["spread"] = metadataGlyph.spread; + metadataJson["text settings"]["size"] = metadataGlyph.size; + metadataJson["text settings"]["weight"] = metadataGlyph.weight; + metadataJson["text settings"]["sdf"] = metadataGlyph.sdf; + metadataJson["text settings"]["shadowbox"] = metadataGlyph.shadowbox; + metadataJson["text settings"]["stroke"] = uf::vector::encode( metadataGlyph.stroke ); + + metadataJson["text settings"]["origin"] = metadataGlyph.origin; + metadataJson["text settings"]["align"] = metadataGlyph.align; + metadataJson["text settings"]["direction"] = metadataGlyph.direction; + + for ( auto& key : ::metadataKeys ) { + if ( !ext::json::isNull( metadataJson[key] ) ) + metadataJson["gui"][key] = metadataJson[key]; + if ( !ext::json::isNull( metadataJson["text settings"][key] ) ) + metadataJson["gui"][key] = metadataJson["text settings"][key]; + } + }; + metadataGlyph.deserialize = [&]() { + for ( auto& key : ::metadataKeys ) { + if ( !ext::json::isNull( metadataJson[key] ) ) metadataJson["gui"][key] = metadataJson[key]; + if ( !ext::json::isNull( metadataJson["text settings"][key] ) ) metadataJson["gui"][key] = metadataJson["text settings"][key]; + } + metadataGlyph.font = metadataJson["gui"]["font"].as(); + metadataGlyph.string = metadataJson["gui"]["string"].as(); + + metadataGlyph.scale = metadataJson["gui"]["scale"].as(); + metadataGlyph.padding = uf::vector::decode( metadataJson["gui"]["padding"], metadataGlyph.padding ); + metadataGlyph.spread = metadataJson["gui"]["spread"].as(); + metadataGlyph.size = metadataJson["gui"]["size"].as(); + metadataGlyph.weight = metadataJson["gui"]["weight"].as(); + metadataGlyph.sdf = metadataJson["gui"]["sdf"].as(); + metadataGlyph.shadowbox = metadataJson["gui"]["shadowbox"].as(); + metadataGlyph.stroke = uf::vector::decode( metadataJson["gui"]["stroke"], metadataGlyph.stroke ); + + metadataGlyph.origin = metadataJson["gui"]["origin"].as(); + metadataGlyph.align = metadataJson["gui"]["align"].as(); + metadataGlyph.direction = metadataJson["gui"]["direction"].as(); + }; + this->addHook( "object:UpdateMetadata.%UID%", metadataGlyph.deserialize); + #if 0 + metadataGlyph.deserialize(); + { std::vector glyphs = this->as().generateGlyphs(); - std::string font = uf::io::root+"/fonts/" + metadata["text settings"]["font"].as(); + std::string font = uf::io::root+"/fonts/" + metadataGlyph.font; std::string key = ""; { - key += metadata["text settings"]["padding"][0].as() + ","; - key += metadata["text settings"]["padding"][1].as() + ";"; - key += metadata["text settings"]["spread"].as() + ";"; - key += metadata["text settings"]["size"].as() + ";"; - key += metadata["text settings"]["font"].as() + ";"; - key += metadata["text settings"]["sdf"].as(); + key += std::to_string(metadataGlyph.padding[0]) + ","; + key += std::to_string(metadataGlyph.padding[1]) + ";"; + key += std::to_string(metadataGlyph.spread) + ";"; + key += std::to_string(metadataGlyph.size) + ";"; + key += metadataGlyph.font + ";"; + key += std::to_string(metadataGlyph.sdf); } auto& scene = uf::scene::getCurrentScene(); - auto& atlas = this->getComponent(); + auto& atlas = this->getComponent(); auto& images = atlas.getImages(); auto& mesh = this->getComponent(); auto& graphic = this->getComponent(); - mesh.vertices.reserve( glyphs.size() * 6 ); + if ( metadataJson["mode"].as() == "flat" ) { + if ( ext::json::isNull(metadataJson["projection"]) ) metadataJson["projection"] = false; + if ( ext::json::isNull(metadataJson["front face"]) ) metadataJson["front face"] = "ccw"; + #if UF_USE_OPENGL + metadataJson["cull mode"] = "front"; + // metadataJson["depth test"]["test"] = false; + // metadataJson["depth test"]["write"] = true; + #endif + } else { + if ( ext::json::isNull(metadataJson["projection"]) ) metadataJson["projection"] = true; + if ( ext::json::isNull(metadataJson["front face"]) ) metadataJson["front face"] = "cw"; + } + metadataJson["cull mode"] = "none"; + graphic.descriptor.parse( metadataJson ); + + mesh.vertices.reserve( glyphs.size() * 6 ); std::unordered_map glyphHashMap; for ( auto& g : glyphs ) { auto glyphKey = std::to_string((uint64_t) g.code) + ";"+key; auto& glyph = ::glyphs.cache[font][glyphKey]; - + #if UF_USE_OPENGL + const uint8_t* buffer = glyph.getBuffer(); + uf::Image::container_t pixels; + std::size_t len = glyph.getSize().x * glyph.getSize().y; + pixels.reserve( len * 4 ); + for ( size_t i = 0; i < len; ++i ) { + pixels.emplace_back( buffer[i] ); + pixels.emplace_back( buffer[i] ); + pixels.emplace_back( buffer[i] ); + pixels.emplace_back( buffer[i] ); + } + glyphHashMap[glyphKey] = atlas.addImage( &pixels[0], glyph.getSize(), 8, 4, true ); + #else glyphHashMap[glyphKey] = atlas.addImage( glyph.getBuffer(), glyph.getSize(), 8, 1, true ); + #endif } atlas.generate(); - float scale = metadata["text settings"]["scale"].as(); + float scale = metadataGlyph.scale; auto& transform = this->getComponent>(); transform.scale.x = scale; transform.scale.y = scale; @@ -701,7 +732,7 @@ void ext::GuiBehavior::initialize( uf::Object& self ) { auto& vertex = mesh.vertices[i+j]; vertex.position.x /= ext::gui::size.reference.x; vertex.position.y /= ext::gui::size.reference.y; - + vertex.position.z = metadata.depth; vertex.uv.y = 1 - vertex.uv.y; } } @@ -719,8 +750,8 @@ void ext::GuiBehavior::initialize( uf::Object& self ) { std::string vertex = uf::io::root+"/shaders/gui/text.vert.spv"; std::string fragment = uf::io::root+"/shaders/gui/text.frag.spv"; } filenames; - if ( metadata["shaders"]["vertex"].is() ) filenames.vertex = metadata["shaders"]["vertex"].as(); - if ( metadata["shaders"]["fragment"].is() ) filenames.fragment = metadata["shaders"]["fragment"].as(); + if ( metadataJson["shaders"]["vertex"].is() ) filenames.vertex = metadataJson["shaders"]["vertex"].as(); + if ( metadataJson["shaders"]["fragment"].is() ) filenames.fragment = metadataJson["shaders"]["fragment"].as(); else if ( suffix != "" ) filenames.fragment = uf::io::root+"/shaders/gui/text."+suffix+"frag.spv"; graphic.material.initializeShaders({ @@ -728,43 +759,40 @@ void ext::GuiBehavior::initialize( uf::Object& self ) { {filenames.fragment, uf::renderer::enums::Shader::FRAGMENT}, }); } - #endif - + #endif this->addHook( "object:Reload.%UID%", [&](ext::json::Value& json){ - if ( json["old"]["text settings"]["string"] == json["new"]["text settings"]["string"] ) return; this->queueHook( "gui:UpdateString.%UID%"); }); - #if UF_USE_FREETYPE this->addHook( "gui:UpdateString.%UID%", [&](ext::json::Value& json){ - for ( auto it = ::defaultSettings["metadata"]["text settings"].begin(); it != ::defaultSettings["metadata"]["text settings"].end(); ++it ) { - std::string key = it.key(); - if ( ext::json::isNull( metadata["text settings"][key] ) ) { - metadata["text settings"][key] = ::defaultSettings["metadata"]["text settings"][key]; - } - } - if ( json["string"].is() ) { - metadata["text settings"]["string"] = json["string"]; - } - std::string string = metadata["text settings"]["string"].as(); + ext::json::forEach(::defaultSettings["metadata"]["text settings"], [&]( const std::string& key, ext::json::Value& value ){ + if ( ext::json::isNull( metadataJson["text settings"][key] ) ) + metadataJson["text settings"][key] = value; + }); + if ( json["string"].is() ) metadataJson["text settings"]["string"] = json["string"]; + std::string string = metadataJson["text settings"]["string"].as(); + + + auto& metadataGlyph = this->getComponent(); + bool first = metadataGlyph.string == "" || json["first"].as(); + metadataGlyph.deserialize(); std::vector glyphs = this->as().generateGlyphs( string ); - - std::string font = uf::io::root+"/fonts/" + metadata["text settings"]["font"].as(); + std::string font = uf::io::root+"/fonts/" + metadataGlyph.font; std::string key = ""; { - key += metadata["text settings"]["padding"][0].as() + ","; - key += metadata["text settings"]["padding"][1].as() + ";"; - key += metadata["text settings"]["spread"].as() + ";"; - key += metadata["text settings"]["size"].as() + ";"; - key += metadata["text settings"]["font"].as() + ";"; - key += metadata["text settings"]["sdf"].as(); + key += std::to_string(metadataGlyph.padding[0]) + ","; + key += std::to_string(metadataGlyph.padding[1]) + ";"; + key += std::to_string(metadataGlyph.spread) + ";"; + key += std::to_string(metadataGlyph.size) + ";"; + key += metadataGlyph.font + ";"; + key += std::to_string(metadataGlyph.sdf); } auto& scene = uf::scene::getCurrentScene(); - auto& atlas = this->getComponent(); - auto& images = atlas.getImages(); auto& mesh = this->getComponent(); auto& graphic = this->getComponent(); - if ( !json["first"].as() ) { + auto& atlas = this->getComponent(); + auto& images = atlas.getImages(); + if ( !first ) { atlas.clear(); mesh.vertices.clear(); mesh.indices.clear(); @@ -778,13 +806,25 @@ void ext::GuiBehavior::initialize( uf::Object& self ) { for ( auto& g : glyphs ) { auto glyphKey = std::to_string((uint64_t) g.code) + ";"+key; auto& glyph = ::glyphs.cache[font][glyphKey]; - + #if UF_USE_OPENGL + const uint8_t* buffer = glyph.getBuffer(); + uf::Image::container_t pixels; + std::size_t len = glyph.getSize().x * glyph.getSize().y; + pixels.reserve( len * 2 ); + for ( size_t i = 0; i < len; ++i ) { + pixels.emplace_back( buffer[i] ); + pixels.emplace_back( buffer[i] ); + } + glyphHashMap[glyphKey] = atlas.addImage( &pixels[0], glyph.getSize(), 8, 2, true ); + #else glyphHashMap[glyphKey] = atlas.addImage( glyph.getBuffer(), glyph.getSize(), 8, 1, true ); + #endif } atlas.generate(); + atlas.clear(false); - float scale = metadata["text settings"]["scale"].as(); + float scale = metadataGlyph.scale; auto& transform = this->getComponent>(); transform.scale.x = scale; transform.scale.y = scale; @@ -806,15 +846,14 @@ void ext::GuiBehavior::initialize( uf::Object& self ) { auto& vertex = mesh.vertices[i+j]; vertex.position.x /= ext::gui::size.reference.x; vertex.position.y /= ext::gui::size.reference.y; - - vertex.uv.y = 1 - vertex.uv.y; + vertex.position.z = metadata.depth; } } auto& texture = graphic.material.textures.emplace_back(); texture.loadFromImage( atlas.getAtlas() ); - if ( json["first"].as() ) { + if ( first ) { graphic.initialize( ::defaultRenderMode ); graphic.initializeMesh( mesh ); @@ -826,8 +865,8 @@ void ext::GuiBehavior::initialize( uf::Object& self ) { std::string vertex = uf::io::root+"/shaders/gui/text.vert.spv"; std::string fragment = uf::io::root+"/shaders/gui/text.frag.spv"; } filenames; - if ( metadata["shaders"]["vertex"].is() ) filenames.vertex = metadata["shaders"]["vertex"].as(); - if ( metadata["shaders"]["fragment"].is() ) filenames.fragment = metadata["shaders"]["fragment"].as(); + if ( metadataJson["shaders"]["vertex"].is() ) filenames.vertex = metadataJson["shaders"]["vertex"].as(); + if ( metadataJson["shaders"]["fragment"].is() ) filenames.fragment = metadataJson["shaders"]["fragment"].as(); else if ( suffix != "" ) filenames.fragment = uf::io::root+"/shaders/gui/text."+suffix+"frag.spv"; graphic.material.initializeShaders({ @@ -839,24 +878,25 @@ void ext::GuiBehavior::initialize( uf::Object& self ) { graphic.getPipeline().update( graphic ); } }); - #endif + this->callHook("gui:UpdateString.%UID%"); } +#endif } void ext::GuiBehavior::tick( uf::Object& self ) { - uf::Serializer& metadata = this->getComponent(); #if 0 - if ( metadata["text settings"]["fade in speed"].is() && !metadata["system"]["faded in"].as() ) { - float speed = metadata["text settings"]["fade in speed"].as(); - float alpha = metadata["text settings"]["color"][3].as(); + uf::Serializer& metadataJson = this->getComponent(); + if ( metadataJson["text settings"]["fade in speed"].is() && !metadataJson["system"]["faded in"].as() ) { + float speed = metadataJson["text settings"]["fade in speed"].as(); + float alpha = metadataJson["text settings"]["color"][3].as(); speed *= uf::physics::time::delta; if ( alpha < 1 && alpha + speed > 1 ) { alpha = 1; speed = 0; - metadata["system"]["faded in"] = true; + metadataJson["system"]["faded in"] = true; } if ( alpha + speed <= 1 ) { - metadata["text settings"]["color"][3] = alpha + speed; + metadataJson["text settings"]["color"][3] = alpha + speed; } } #endif @@ -894,7 +934,8 @@ struct GlyphUniformDescriptor { } gui; }; void ext::GuiBehavior::render( uf::Object& self ){ - uf::Serializer& metadata = this->getComponent(); + auto& metadata = this->getComponent(); + auto& metadataJson = this->getComponent(); /* Update uniforms */ if ( this->hasComponent() ) { auto& scene = uf::scene::getCurrentScene(); auto& graphic = this->getComponent(); @@ -902,20 +943,23 @@ void ext::GuiBehavior::render( uf::Object& self ){ auto& camera = controller.getComponent(); auto& transform = this->getComponent>(); if ( !graphic.initialized ) return; + + bool isGlyph = this->hasComponent(); //metadataGlyph.string != ""; #if UF_USE_OPENGL auto model = uf::matrix::identity(); auto uniformBuffer = graphic.getUniform(); pod::Uniform& uniform = *((pod::Uniform*) graphic.device->getBuffer(uniformBuffer.buffer)); uniform.projection = uf::matrix::identity(); - if ( metadata["gui"]["only model"].as() ) { + if ( metadata.mode == 1 ) { uniform.modelView = transform.model; - } else if ( metadata["gui"]["world"].as() ) { + } else if ( metadata.mode == 2 ) { auto& scene = uf::scene::getCurrentScene(); auto& controller = scene.getController(); auto& camera = controller.getComponent(); uniform.projection = camera.getProjection(); uniform.modelView = camera.getView() * uf::transform::model( transform ); - } else if ( metadata["gui"]["projection"].as() ) { + model = uniform.modelView; + } else if ( metadata.mode == 3 ) { pod::Transform<> flatten = uf::transform::flatten( transform ); uniform.projection = camera.getProjection(); uniform.modelView = @@ -923,15 +967,25 @@ void ext::GuiBehavior::render( uf::Object& self ){ uf::matrix::scale( uf::matrix::identity(), flatten.scale ) * uf::quaternion::matrix( flatten.orientation ) * flatten.model; + model = uniform.modelView; } else { pod::Transform<> flatten = uf::transform::flatten( transform ); + model = + uf::matrix::translate( uf::matrix::identity(), flatten.position ) * + uf::matrix::scale( uf::matrix::identity(), flatten.scale ) * + uf::quaternion::matrix( flatten.orientation ) * + flatten.model; + + flatten.position.y = -flatten.position.y; + if ( isGlyph ) flatten.scale.y = -flatten.scale.y; + + flatten.position.z = 1; uniform.modelView = uf::matrix::translate( uf::matrix::identity(), flatten.position ) * uf::matrix::scale( uf::matrix::identity(), flatten.scale ) * uf::quaternion::matrix( flatten.orientation ) * flatten.model; } - graphic.updateUniform( &uniform, sizeof(uniform) ); #else if ( !graphic.material.hasShader("vertex") ) return; @@ -940,61 +994,23 @@ void ext::GuiBehavior::render( uf::Object& self ){ auto& uniform = shader.getUniform("UBO"); auto& uniforms = uniform.get>(); - bool isGlyph = metadata["text settings"]["string"].is(); - std::vector keys = { - "uv", - "shader", - "depth", - "color", - "world", - "projection", - "only model", - "sdf", - "shadowbox", - "stroke", - "weight", - "spread", - "scale", - "alpha", - }; - for ( auto& key : keys ) { - if ( !ext::json::isNull( metadata[key] ) ) - metadata["gui"][key] = metadata[key]; - if ( !ext::json::isNull( metadata["text settings"][key] ) ) - metadata["gui"][key] = metadata["text settings"][key]; - } + uniforms.gui.offset = metadata.uv; + uniforms.gui.mode = metadata.shader; + uniforms.gui.depth = metadata.depth; - uniforms.gui.offset = { - metadata["gui"]["uv"][0].as(), - metadata["gui"]["uv"][1].as(), - metadata["gui"]["uv"][2].as(), - metadata["gui"]["uv"][3].as() - }; - uniforms.gui.mode = metadata["gui"]["shader"].is() ? metadata["gui"]["shader"].as() : 0; - uniforms.gui.depth = metadata["gui"]["depth"].is() ? metadata["gui"]["depth"].as() : 0; uniforms.gui.depth = 1 - uniforms.gui.depth; - if ( ext::json::isArray( metadata["gui"]["color"] ) ) { - uniforms.gui.color = { - metadata["gui"]["color"][0].as(), - metadata["gui"]["color"][1].as(), - metadata["gui"]["color"][2].as(), - metadata["gui"]["color"][3].as(), - }; - } else { - uniforms.gui.color = { 1, 1, 1, 1 }; - } - if ( metadata["gui"]["alpha"].is() ) { - uniforms.gui.color[3] *= metadata["gui"]["alpha"].as(); - } - for ( std::size_t i = 0; i < 2; ++i ) { - if ( metadata["gui"]["only model"].as() ) { + + uniforms.gui.color = metadata.color; + + for ( std::size_t i = 0; i < uf::renderer::settings::maxViews; ++i ) { + if ( metadata.mode == 1 ) { uniforms.matrices.model[i] = transform.model; - } else if ( metadata["gui"]["world"].as() ) { + } else if ( metadata.mode == 2 ) { auto& scene = uf::scene::getCurrentScene(); auto& controller = scene.getController(); auto& camera = controller.getComponent(); uniforms.matrices.model[i] = camera.getProjection(i) * camera.getView(i) * uf::transform::model( transform ); - } else if ( metadata["gui"]["projection"].as() ) { + } else if ( metadata.mode == 3 ) { pod::Transform<> flatten = uf::transform::flatten( transform ); uniforms.matrices.model[i] = camera.getProjection(i) * @@ -1015,22 +1031,14 @@ void ext::GuiBehavior::render( uf::Object& self ){ // set glyph-based uniforms if ( isGlyph ) { auto& uniforms = uniform.get>(); + auto& metadataGlyph = this->getComponent(); - uniforms.gui.sdf = metadata["gui"]["sdf"].as(); - uniforms.gui.shadowbox = metadata["gui"]["shadowbox"].as(); - if ( ext::json::isArray( metadata["gui"]["stroke"] ) ) { - uniforms.gui.stroke = { - metadata["gui"]["stroke"][0].as(), - metadata["gui"]["stroke"][1].as(), - metadata["gui"]["stroke"][2].as(), - metadata["gui"]["stroke"][3].as(), - }; - } else { - uniforms.gui.stroke = { 1, 1, 1, 1 }; - } - uniforms.gui.weight = metadata["gui"]["weight"].as(); // float - uniforms.gui.spread = metadata["gui"]["spread"].as(); // int - uniforms.gui.scale = metadata["gui"]["scale"].as(); // float + uniforms.gui.sdf = metadataGlyph.sdf; + uniforms.gui.shadowbox = metadataGlyph.shadowbox; + uniforms.gui.stroke = metadataGlyph.stroke; + uniforms.gui.weight = metadataGlyph.weight; + uniforms.gui.spread = metadataGlyph.spread; + uniforms.gui.scale = metadataGlyph.scale; } shader.updateUniform( "UBO", uniform ); @@ -1040,8 +1048,8 @@ void ext::GuiBehavior::render( uf::Object& self ){ pod::Vector2f min = { 1, 1 }; pod::Vector2f max = { -1, -1 }; - if ( this->hasComponent() ) { - auto& mesh = this->getComponent(); + if ( this->hasComponent() ) { + auto& mesh = this->getComponent(); for ( auto& vertex : mesh.vertices ) { pod::Vector4f position = { vertex.position.x, vertex.position.y, 0, 1 }; // gcc10+ doesn't like implicit template arguments @@ -1066,10 +1074,10 @@ void ext::GuiBehavior::render( uf::Object& self ){ } } - metadata["box"]["min"]["x"] = min.x; - metadata["box"]["min"]["y"] = min.y; - metadata["box"]["max"]["x"] = max.x; - metadata["box"]["max"]["y"] = max.y; + metadata.box.min.x = min.x; + metadata.box.min.y = min.y; + metadata.box.max.x = max.x; + metadata.box.max.y = max.y; } } void ext::GuiBehavior::destroy( uf::Object& self ){} diff --git a/ext/gui/behavior.h b/ext/gui/behavior.h index f50efc23..2f57f06d 100644 --- a/ext/gui/behavior.h +++ b/ext/gui/behavior.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace ext { namespace GuiBehavior { @@ -13,5 +14,46 @@ namespace ext { void tick( uf::Object& ); void render( uf::Object& ); void destroy( uf::Object& ); + struct Metadata { + pod::Vector4f color = {1,1,1,1}; + bool world = false; + pod::Vector2f size = {0,0}; + size_t mode = 0; + struct { + pod::Vector2f min = { 1, 1 }; + pod::Vector2f max = { -1, -1 }; + } box; + bool clicked = false; + bool hovered = false; + + pod::Vector4f uv = {0, 0, 1, 1}; + size_t shader = 0; + float depth = 0; + float alpha = -1; + + std::function serialize; + std::function deserialize; + }; + struct GlyphMetadata { + std::string font = ""; + std::string string = ""; + + float scale = 0; + pod::Vector2f padding = {0,0}; + + float spread = 0; + float size = 0; + float weight = 0; + bool sdf = false; + bool shadowbox = false; + pod::Vector4f stroke = {0,0,0,0}; + + std::string origin = ""; + std::string align = ""; + std::string direction = ""; + + std::function serialize; + std::function deserialize; + }; } } \ No newline at end of file diff --git a/ext/gui/gui.h b/ext/gui/gui.h index 5d700de0..36880df4 100644 --- a/ext/gui/gui.h +++ b/ext/gui/gui.h @@ -22,6 +22,7 @@ namespace pod { namespace ext { class EXT_API Gui : public uf::Object { public: + typedef uf::BaseMesh mesh_t; typedef uf::BaseMesh glyph_mesh_t; // Gui(); std::vector generateGlyphs( const std::string& = "" ); diff --git a/ext/gui/manager/behavior.cpp b/ext/gui/manager/behavior.cpp index fc956794..eb9846b9 100644 --- a/ext/gui/manager/behavior.cpp +++ b/ext/gui/manager/behavior.cpp @@ -35,10 +35,11 @@ ext::gui::Size ext::gui::size = { 0, 0, }, - .reference = { - 1920, - 1080 - }, +#if UF_ENV_DREAMCAST + .reference = { 960, 720 }, +#else + .reference = { 1920, 1080 }, +#endif }; @@ -46,21 +47,16 @@ UF_BEHAVIOR_REGISTER_CPP(ext::GuiManagerBehavior) UF_BEHAVIOR_REGISTER_AS_OBJECT(ext::GuiManagerBehavior, ext::GuiManager) #define this (&self) void ext::GuiManagerBehavior::initialize( uf::Object& self ) { - { - // ext::gui::size.current.x = uf::renderer::settings::width; - // ext::gui::size.current.y = uf::renderer::settings::height; - } // add gui render mode -#if UF_USE_VULKAN if ( !uf::renderer::hasRenderMode( "Gui", true ) ) { auto& renderMode = this->getComponent(); std::string name = "Gui"; uf::renderer::addRenderMode( &renderMode, name ); renderMode.blitter.descriptor.subpass = 1; } -#endif - uf::Serializer& metadata = this->getComponent(); - uf::Asset& assetLoader = this->getComponent(); + + auto& metadataJson = this->getComponent(); + auto& assetLoader = this->getComponent(); this->addHook( "window:Resized", [&](ext::json::Value& json){ @@ -91,11 +87,11 @@ void ext::GuiManagerBehavior::initialize( uf::Object& self ) { { auto& scene = uf::scene::getCurrentScene(); auto& controller = scene.getController(); - auto& metadata = controller.getComponent(); - - if ( metadata["overlay"]["cursor"]["type"].as() == "mouse" ) { - metadata["overlay"]["cursor"]["position"][0] = click.x; - metadata["overlay"]["cursor"]["position"][1] = click.y; + auto& metadata = controller.getComponent(); + auto& metadataJson = controller.getComponent(); + // if ( metadata.cursor.type == "mouse" ) metadata.cursor.position = click; + if ( metadataJson["overlay"]["cursor"]["type"].as() == "mouse" ) { + metadataJson["overlay"]["cursor"]["position"] = uf::vector::encode( click ); } } }); @@ -103,11 +99,11 @@ void ext::GuiManagerBehavior::initialize( uf::Object& self ) { void ext::GuiManagerBehavior::tick( uf::Object& self ) { } void ext::GuiManagerBehavior::render( uf::Object& self ){ +#if UF_USE_VULKAN auto& scene = uf::scene::getCurrentScene(); auto& controller = scene.getController(); auto& camera = controller.getComponent(); - auto& metadata = controller.getComponent(); - + auto& metadataJson = controller.getComponent(); uf::renderer::RenderTargetRenderMode* renderModePointer = NULL; if ( this->hasComponent() ) { @@ -119,7 +115,6 @@ void ext::GuiManagerBehavior::render( uf::Object& self ){ auto& blitter = renderMode.blitter; if ( !blitter.initialized ) return; -#if UF_USE_VULKAN if ( !blitter.material.hasShader("fragment") ) return; struct UniformDescriptor { @@ -140,28 +135,12 @@ void ext::GuiManagerBehavior::render( uf::Object& self ){ for ( size_t i = 0; i < 2; ++i ) { pod::Transform<> transform; - if ( ext::json::isArray( metadata["overlay"]["position"] ) ) - transform.position = { - metadata["overlay"]["position"][0].as(), - metadata["overlay"]["position"][1].as(), - metadata["overlay"]["position"][2].as(), - }; - if ( ext::json::isArray( metadata["overlay"]["scale"] ) ) - transform.scale = { - metadata["overlay"]["scale"][0].as(), - metadata["overlay"]["scale"][1].as(), - metadata["overlay"]["scale"][2].as(), - }; - if ( ext::json::isArray( metadata["overlay"]["orientation"] ) ) - transform.orientation = { - metadata["overlay"]["orientation"][0].as(), - metadata["overlay"]["orientation"][1].as(), - metadata["overlay"]["orientation"][2].as(), - metadata["overlay"]["orientation"][3].as(), - }; + transform.position = uf::vector::decode( metadataJson["overlay"]["position"], transform.position ); + transform.scale = uf::vector::decode( metadataJson["overlay"]["scale"], transform.scale ); + transform.orientation = uf::vector::decode( metadataJson["overlay"]["orientation"], transform.orientation ); #if UF_USE_OPENVR - if ( ext::openvr::enabled && (metadata["overlay"]["enabled"].as() || uf::renderer::getRenderMode("Stereoscopic Deferred", true).getType() == "Stereoscopic Deferred" )) { - if ( metadata["overlay"]["floating"].as() ) { + if ( ext::openvr::enabled && metadataJson["overlay"]["enabled"].as() ) { + if ( metadataJson["overlay"]["floating"].as() ) { pod::Matrix4f model = uf::transform::model( transform ); uniforms.matrices.models[i] = camera.getProjection(i) * ext::openvr::hmdEyePositionMatrix( i == 0 ? vr::Eye_Left : vr::Eye_Right ) * model; } else { @@ -181,12 +160,12 @@ void ext::GuiManagerBehavior::render( uf::Object& self ){ pod::Vector3f cursorSize = { 0, 0 }; - if ( metadata["overlay"]["cursor"]["enabled"].as() ) { - uniforms.cursor.position.x = (metadata["overlay"]["cursor"]["position"][0].as() + 1.0f) * 0.5f; //(::mouse.position.x + 1.0f) * 0.5f; - uniforms.cursor.position.y = (metadata["overlay"]["cursor"]["position"][1].as() + 1.0f) * 0.5f; //(::mouse.position.y + 1.0f) * 0.5f; + if ( metadataJson["overlay"]["cursor"]["enabled"].as() ) { + uniforms.cursor.position.x = (metadataJson["overlay"]["cursor"]["position"][0].as() + 1.0f) * 0.5f; //(::mouse.position.x + 1.0f) * 0.5f; + uniforms.cursor.position.y = (metadataJson["overlay"]["cursor"]["position"][1].as() + 1.0f) * 0.5f; //(::mouse.position.y + 1.0f) * 0.5f; - cursorSize.x = metadata["overlay"]["cursor"]["radius"].as(); - cursorSize.y = metadata["overlay"]["cursor"]["radius"].as(); + cursorSize.x = metadataJson["overlay"]["cursor"]["radius"].as(); + cursorSize.y = metadataJson["overlay"]["cursor"]["radius"].as(); cursorSize = uf::matrix::multiply( uf::matrix::inverse( uf::matrix::scale( uf::matrix::identity() , transform.scale) ), cursorSize ); @@ -194,10 +173,7 @@ void ext::GuiManagerBehavior::render( uf::Object& self ){ uniforms.cursor.radius.y = cursorSize.y; } - uniforms.cursor.color.x = metadata["overlay"]["cursor"]["color"][0].as(); - uniforms.cursor.color.y = metadata["overlay"]["cursor"]["color"][1].as(); - uniforms.cursor.color.z = metadata["overlay"]["cursor"]["color"][2].as(); - uniforms.cursor.color.w = metadata["overlay"]["cursor"]["color"][3].as(); + uniforms.cursor.color = uf::vector::decode( metadataJson["overlay"]["cursor"]["color"], pod::Vector4f{0,0,0,0} ); } shader.updateUniform( "UBO", uniform ); diff --git a/ext/gui/manager/behavior.h b/ext/gui/manager/behavior.h index 63347044..9d45bdc1 100644 --- a/ext/gui/manager/behavior.h +++ b/ext/gui/manager/behavior.h @@ -13,5 +13,8 @@ namespace ext { void tick( uf::Object& ); void render( uf::Object& ); void destroy( uf::Object& ); + struct Metadata { + + }; } } \ No newline at end of file diff --git a/ext/main.cpp b/ext/main.cpp index f2ead868..e1542ce4 100644 --- a/ext/main.cpp +++ b/ext/main.cpp @@ -706,14 +706,7 @@ void EXT_API ext::tick() { ++::times.frames; double every = fps["every"].as(); TIMER( every ) { - // UF_DEBUG_MSG("Framerate: " << (1.0/times.deltaTime) << " FPS | Frametime: " << (times.deltaTime * 1000) << "ms"); UF_DEBUG_MSG("System: " << (every * 1000.0/::times.frames) << " ms/frame | Time: " << time << " | Frames: " << ::times.frames << " | FPS: " << ::times.frames / time); - #if UF_ENV_DREAMCAST - // pvr_stats_t stats; - // pvr_get_stats(&stats); - // UF_DEBUG_MSG("PVR stats: " << stats.frame_last_time << " ms | " << stats.frame_rate << " fps | " << stats.reg_last_time << " ms | " << stats.rnd_last_time << " ms | " << stats.vtx_buffer_used << " bytes | " << stats.vtx_buffer_used_max << " bytes | " << stats.buf_last_time << " ms" ); - #endif - ::times.frames = 0; } } diff --git a/makefiles/win64.gcc.make b/makefiles/win64.gcc.make index 2ec3e74c..4ec6b027 100644 --- a/makefiles/win64.gcc.make +++ b/makefiles/win64.gcc.make @@ -1,4 +1,4 @@ ARCH = win64 PREFIX = gcc CC = /opt/mingw-w64/x86_64-7.2.0-posix-seh-rt_v5-rev1/mingw64/bin/g++ -FLAGS += -Wno-unknown-pragmas -std=c++17 -O2 -g -fdiagnostics-color=always -Wall -Wno-conversion-null -Wno-unused-function -Wno-unused-variable -Wno-switch -Wno-reorder -Wno-sign-compare -Wno-unused-but-set-variable -Wno-ignored-attributes -Wno-narrowing -Wno-misleading-indentation \ No newline at end of file +FLAGS += -Wno-unknown-pragmas -std=c++17 -Og -g -fdiagnostics-color=always -Wall -Wno-conversion-null -Wno-unused-function -Wno-unused-variable -Wno-switch -Wno-reorder -Wno-sign-compare -Wno-unused-but-set-variable -Wno-ignored-attributes -Wno-narrowing -Wno-misleading-indentation \ No newline at end of file