lua optimizations to remove as much overhead as possible (to almost nothing), adjusted how metadata is accessed in lua (it requires explicit pasting of macros)

This commit is contained in:
ecker 2025-08-17 20:48:20 -05:00
parent 0a299a3fd2
commit c9448f9b74
27 changed files with 341 additions and 247 deletions

View File

@ -12,7 +12,8 @@ local ent = ent
local scene = entities.currentScene() local scene = entities.currentScene()
local controller = entities.controller() local controller = entities.controller()
local camera = controller:getComponent("Camera") local camera = controller:getComponent("Camera")
local metadata = ent:getComponent("Metadata") local metadataJson = ent:getComponent("Metadata")
local metadata = ent:getComponent("GuiBehavior::Metadata")
local masterdata = scene:getComponent("Metadata") local masterdata = scene:getComponent("Metadata")
local soundEmitter = ent:loadChild("./sound.json",true) local soundEmitter = ent:loadChild("./sound.json",true)
@ -76,7 +77,7 @@ local selectableElements = {
} }
local selectableElementColors = {} local selectableElementColors = {}
local selectedElement = 0 local selectedElement = 0
local selectionColor = { 1, 0, 1, 1 } local selectionColor = Vector4f( 1, 0, 1, 1 )
local INPUT_DELAY = 0.2 local INPUT_DELAY = 0.2
local function array_index_of( haystack, needle ) local function array_index_of( haystack, needle )
@ -87,6 +88,8 @@ local function array_index_of( haystack, needle )
end end
return 0 return 0
end end
local function onHover( payload ) local function onHover( payload )
playSound( "buttonrollover" ) playSound( "buttonrollover" )
selectedElement = 0 selectedElement = 0
@ -142,18 +145,20 @@ ent:bind( "tick", function(self)
static.alpha = 0 static.alpha = 0
end end
metadata["initialized"] = true;
if static.alpha >= 1.0 then if static.alpha >= 1.0 then
static.alpha = 1.0 static.alpha = 1.0
else else
static.alpha = static.alpha + time.delta() * 1.5 static.alpha = static.alpha + time.delta() * 1.5
end end
metadata.initialized = true
-- make background glow -- make background glow
local glow = 1 + math.sin(1.25 * time.current()) * 0.125 local glow = 1 + math.sin(1.25 * time.current()) * 0.125
metadata["color"] = { glow, glow, glow, static.alpha } metadata.color.x = glow
self:setComponent("Metadata", metadata) metadata.color.y = glow
metadata.color.z = glow
metadata.color.w = static.alpha
camera:update(true); camera:update(true);
@ -161,37 +166,35 @@ ent:bind( "tick", function(self)
for k, v in pairs(children) do for k, v in pairs(children) do
if v:uid() <= 0 then goto continue end if v:uid() <= 0 then goto continue end
-- set alpha local metadata = v:getComponent("GuiBehavior::Metadata")
local metadata = v:getComponent("Metadata")
local index = array_index_of( selectableElements, v ) local index = array_index_of( selectableElements, v )
-- mark element as hovered if selected -- mark element as hovered if selected
if 0 < selectedElement and selectedElement <= #selectableElements then if 0 < selectedElement and selectedElement <= #selectableElements then
if 0 < index and index <= #selectableElements then if 0 < index and index <= #selectableElements then
metadata["hovered"] = index == selectedElement metadata.hovered = index == selectedElement
end end
end end
if metadata["clickable"] then if metadata.clickable then
-- backup color -- backup color
if selectableElementColors[index] == nil then if selectableElementColors[index] == nil then
selectableElementColors[index] = metadata["color"] selectableElementColors[index] = Vector4f(metadata.color)
end end
-- color for selection -- color for selection
if metadata["hovered"] then if metadata.hovered then
metadata["color"] = selectionColor metadata.color = selectionColor
-- simulate click on input press -- simulate click on input press
if (inputs.key("A") or inputs.key("START") or inputs.key("Enter")) and timer:elapsed() >= INPUT_DELAY then if (inputs.key("A") or inputs.key("START") or inputs.key("Enter")) and timer:elapsed() >= INPUT_DELAY then
timer:reset() timer:reset()
v:callHook("gui:Clicked.%UID%", {}) v:callHook("gui:Clicked.%UID%", {})
end end
else else
metadata["color"] = selectableElementColors[index] metadata.color = selectableElementColors[index]
end end
end end
-- set alpha
metadata["color"][4] = static.alpha metadata.color.w = static.alpha
v:setComponent("Metadata", metadata)
local transform = v:getComponent("Transform") local transform = v:getComponent("Transform")
local static = Static.get(v) local static = Static.get(v)
@ -207,7 +210,6 @@ ent:bind( "tick", function(self)
transform.position = Vector3f.lerp( static.from, static.to, static.delta ) transform.position = Vector3f.lerp( static.from, static.to, static.delta )
end end
::continue:: ::continue::
end end
@ -217,10 +219,8 @@ ent:bind( "tick", function(self)
local static = Static.get( child ) local static = Static.get( child )
local transform = child:getComponent("Transform") local transform = child:getComponent("Transform")
local metadata = child:getComponent("Metadata") local metadata = child:getComponent("GuiBehavior::Metadata")
local speed = metadata.hovered and 0.25 or 0.0125
-- rotation
local speed = metadata["hovered"] and 0.25 or 0.0125
static.time = (static.time or 0) + time.delta() * -speed static.time = (static.time or 0) + time.delta() * -speed
transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time ) transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time )
end end
@ -230,10 +230,8 @@ ent:bind( "tick", function(self)
local static = Static.get( child ) local static = Static.get( child )
local transform = child:getComponent("Transform") local transform = child:getComponent("Transform")
local metadata = child:getComponent("Metadata") local metadata = child:getComponent("GuiBehavior::Metadata")
local speed = metadata.hovered and 0.25 or 0.0125
-- rotation
local speed = metadata["hovered"] and 0.25 or 0.0125
static.time = (static.time or 0) + time.delta() * speed static.time = (static.time or 0) + time.delta() * speed
transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time ) transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time )
end end

View File

@ -1,7 +1,8 @@
local ent = ent local ent = ent
local scene = entities.currentScene() local scene = entities.currentScene()
local controller = entities.controller() local controller = entities.controller()
local metadata = ent:getComponent("Metadata") local metadataJson = ent:getComponent("Metadata")
local metadata = ent:getComponent("GuiBehavior::Metadata")
local masterdata = scene:getComponent("Metadata") local masterdata = scene:getComponent("Metadata")
local children = { local children = {
@ -51,12 +52,13 @@ local playSound = function( key )
-- assetLoader:cache(soundEmitter:formatHookName("asset:Load.%UID%"), string.resolveURI(url), "") -- assetLoader:cache(soundEmitter:formatHookName("asset:Load.%UID%"), string.resolveURI(url), "")
end end
local closing = false
local closed = false
local onClose = nil
ent:addHook("menu:Close.%UID%", function( json ) ent:addHook("menu:Close.%UID%", function( json )
--playSound("menu close") --playSound("menu close")
if metadata["system"]["hooks"] == nil then metadata["system"]["hooks"] = {} end closing = true
metadata["system"]["hooks"]["onClose"] = json["callback"]; onClose = json["callback"];
metadata["system"]["closing"] = true;
ent:setComponent("Metadata", metadata)
end ) end )
--playSound("menu open") --playSound("menu open")
@ -67,7 +69,7 @@ local selectableElements = {
} }
local selectableElementColors = {} local selectableElementColors = {}
local selectedElement = 0 local selectedElement = 0
local selectionColor = { 1, 0, 1, 1 } local selectionColor = Vector4f( 1, 0, 1, 1 )
local INPUT_DELAY = 0.2 local INPUT_DELAY = 0.2
local function array_index_of( haystack, needle ) local function array_index_of( haystack, needle )
@ -140,30 +142,29 @@ ent:bind( "tick", function(self)
end end
-- handle closing -- handle closing
if metadata["system"]["closing"] then if closing then
if static.alpha <= 0 then if static.alpha <= 0 then
static.alpha = 0 static.alpha = 0
metadata["system"]["closing"] = false closing = false
metadata["system"]["closed"] = true closed = true
else else
static.alpha = static.alpha - time.delta() static.alpha = static.alpha - time.delta()
end end
elseif metadata["system"]["closed"] then elseif closed then
timer:stop() timer:stop()
local callback = metadata["system"]["hooks"]["onClose"] if onClose then
if callback then local payload = onClose["payload"]
local payload = callback["payload"]
local target = self local target = self
if callback["scope"] == "parent" then if onClose["scope"] == "parent" then
target = ent:getParent() target = ent:getParent()
elseif callback["scope"] == "scene" then elseif onClose["scope"] == "scene" then
target = scene target = scene
end end
if type(callback["delay"]) == "number" and target:uid() ~= self:uid() then if type(onClose["delay"]) == "number" and target:uid() ~= self:uid() then
target:queueHook( callback["name"], payload, callback["delay"] ); target:queueHook( onClose["name"], payload, onClose["delay"] );
else else
target:callHook( callback["name"], payload ); target:callHook( onClose["name"], payload );
end end
end end
@ -171,10 +172,10 @@ ent:bind( "tick", function(self)
-- scene:queueHook("system:Destroy", { uid = self:uid() }, 0) -- scene:queueHook("system:Destroy", { uid = self:uid() }, 0)
return return
else else
if not metadata["initialized"] then if not metadata.initialized then
static.alpha = 0 static.alpha = 0
end end
metadata["initialized"] = true; metadata.initialized = true;
if static.alpha >= 1.0 then if static.alpha >= 1.0 then
static.alpha = 1.0 static.alpha = 1.0
else else
@ -182,42 +183,41 @@ ent:bind( "tick", function(self)
end end
end end
metadata["color"][4] = static.alpha; metadata.color.w = static.alpha
-- set alphas -- set alphas
for k, v in pairs(children) do for k, v in pairs(children) do
if v:uid() <= 0 then goto continue end if v:uid() <= 0 then goto continue end
-- set alpha local metadata = v:getComponent("GuiBehavior::Metadata")
local metadata = v:getComponent("Metadata")
local index = array_index_of( selectableElements, v ) local index = array_index_of( selectableElements, v )
-- mark element as hovered if selected -- mark element as hovered if selected
if 0 < selectedElement and selectedElement <= #selectableElements then if 0 < selectedElement and selectedElement <= #selectableElements then
if 0 < index and index <= #selectableElements then if 0 < index and index <= #selectableElements then
metadata["hovered"] = index == selectedElement metadata.hovered = index == selectedElement
end end
end end
if metadata["clickable"] then if metadata.clickable then
-- backup color -- backup color
if selectableElementColors[index] == nil then if selectableElementColors[index] == nil then
selectableElementColors[index] = metadata["color"] selectableElementColors[index] = Vector4f(metadata.color)
end end
-- color for selection -- color for selection
if metadata["hovered"] then if metadata.hovered then
metadata["color"] = selectionColor metadata.color = selectionColor
-- simulate click on input press -- simulate click on input press
if (inputs.key("A") or inputs.key("Enter")) and timer:elapsed() >= INPUT_DELAY then if (inputs.key("A") or inputs.key("START") or inputs.key("Enter")) and timer:elapsed() >= INPUT_DELAY then
timer:reset() timer:reset()
v:callHook("gui:Clicked.%UID%", {}) v:callHook("gui:Clicked.%UID%", {})
end end
else else
metadata["color"] = selectableElementColors[index] metadata.color = selectableElementColors[index]
end end
end end
metadata["color"][4] = static.alpha -- set alpha
v:setComponent("Metadata", metadata) metadata.color.w = static.alpha
local transform = v:getComponent("Transform") local transform = v:getComponent("Transform")
local static = Static.get(v) local static = Static.get(v)
@ -237,26 +237,24 @@ ent:bind( "tick", function(self)
end end
-- circle in -- circle in
if children.circleIn:uid() > 0 then child = children.circleIn
local static = Static.get( children.circleIn ) if child:uid() > 0 then
local static = Static.get( child )
local transform = children.circleIn:getComponent("Transform") local transform = child:getComponent("Transform")
local metadata = children.circleIn:getComponent("Metadata") local metadata = child:getComponent("GuiBehavior::Metadata")
local speed = metadata.hovered and 0.25 or 0.0125
-- rotation
local speed = metadata["hovered"] and 0.25 or 0.0125
static.time = (static.time or 0) + time.delta() * -speed static.time = (static.time or 0) + time.delta() * -speed
transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time ) transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time )
end end
-- circle out -- circle out
if children.circleOut:uid() > 0 then child = children.circleOut
local static = Static.get( children.circleOut ) if child:uid() > 0 then
local static = Static.get( child )
local transform = children.circleOut:getComponent("Transform") local transform = child:getComponent("Transform")
local metadata = children.circleOut:getComponent("Metadata") local metadata = child:getComponent("GuiBehavior::Metadata")
local speed = metadata.hovered and 0.25 or 0.0125
-- rotation
local speed = metadata["hovered"] and 0.25 or 0.0125
static.time = (static.time or 0) + time.delta() * speed static.time = (static.time or 0) + time.delta() * speed
transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time ) transform.orientation = Quaternion.axisAngle( Vector3f(0, 0, 1), static.time )
end end

View File

@ -12,55 +12,6 @@ local timers = {
} }
if not timers.lookat:running() then timers.lookat:start(); end if not timers.lookat:running() then timers.lookat:start(); end
--[[
-- setup held object locals
local heldObject = {
uid = 0,
distance = 0,
smoothSpeed = 4,
scrollSpeed = 16,
momentum = Vector3f(0,0,0),
rotate = false,
}
-- setup light locals
local light = {
entity = nil
}
for k, v in pairs(ent:getChildren()) do
if v:name() == "Light" then
light.entity = v
end
end
if light.entity == nil then
light.entity = ent:loadChild("./playerLight.json",true)
end
light.metadata = light.entity:getComponent("Metadata")
light.transform = light.entity:getComponent("Transform")
light.power = light.metadata["light"]["power"]
light.origin = Vector3f(light.transform.position)
light.entity:setComponent("Metadata", { light = { power = 0 } })
-- sound emitter
local playSound = function( key, loop )
if not loop then loop = false end
local url = "/ui/" .. key .. ".ogg"
ent:callHook("sound:Emit.%UID%", {
filename = string.resolveURI(url, metadata["system"]["root"]),
spatial = true,
streamed = true,
volume = "sfx",
loop = loop
}, 0)
end
local stopSound = function( key )
local url = "/ui/" .. key .. ".ogg"
ent:callHook("sound:Stop.%UID%", {
filename = string.resolveURI(url, metadata["system"]["root"])
}, 0)
end
]]
local collider = ent:getComponent("PhysicsState") local collider = ent:getComponent("PhysicsState")
local target_transform = nil local target_transform = nil
local soundEmitter = ent local soundEmitter = ent

View File

@ -1,11 +1,13 @@
local ent = ent local ent = ent
local scene = entities.currentScene() local scene = entities.currentScene()
local metadata = ent:getComponent("Metadata") local metadataJson = ent:getComponent("Metadata")
local transform = ent:getComponent("Transform") local transform = ent:getComponent("Transform")
local physicsState = ent:getComponent("PhysicsState") local physicsState = ent:getComponent("Physics")
local camera = ent:getComponent("Camera") local camera = ent:getComponent("Camera")
local cameraTransform = camera:getTransform() local cameraTransform = camera:getTransform()
local fixedCamera = metadataJson["camera"]["settings"]["fixed"]
-- setup all timers -- setup all timers
local timers = { local timers = {
use = Timer.new(), use = Timer.new(),
@ -29,7 +31,7 @@ local heldObject = {
} }
-- setup light locals -- setup light locals
local light = { local light = {
entity = nil entity = nil,
} }
for k, v in pairs(ent:getChildren()) do for k, v in pairs(ent:getChildren()) do
if type(v) == "number" then if type(v) == "number" then
@ -44,18 +46,19 @@ end
if light.entity == nil then if light.entity == nil then
light.entity = ent:loadChild("./playerLight.json",true) light.entity = ent:loadChild("./playerLight.json",true)
end end
light.metadata = light.entity:getComponent("Metadata") light.metadata = light.entity:getComponent("LightBehavior::Metadata")
light.transform = light.entity:getComponent("Transform") light.transform = light.entity:getComponent("Transform")
light.power = light.metadata["light"]["power"] light.power = light.metadata.power
light.origin = Vector3f(light.transform.position) light.origin = Vector3f(light.transform.position)
light.entity:setComponent("Metadata", { light = { power = 0 } }) light.metadata.power = 0
--light.entity:setComponent("Metadata", { light = { power = 0 } })
-- sound emitter -- sound emitter
local playSound = function( key, loop ) local playSound = function( key, loop )
if not loop then loop = false end if not loop then loop = false end
local url = "/ui/" .. key .. ".ogg" local url = "/ui/" .. key .. ".ogg"
ent:callHook("sound:Emit.%UID%", { ent:callHook("sound:Emit.%UID%", {
filename = string.resolveURI(url, metadata["system"]["root"]), filename = string.resolveURI(url, metadataJson["system"]["root"]),
spatial = true, spatial = true,
streamed = true, streamed = true,
volume = "sfx", volume = "sfx",
@ -65,7 +68,7 @@ end
local stopSound = function( key ) local stopSound = function( key )
local url = "/ui/" .. key .. ".ogg" local url = "/ui/" .. key .. ".ogg"
ent:callHook("sound:Stop.%UID%", { ent:callHook("sound:Stop.%UID%", {
filename = string.resolveURI(url, metadata["system"]["root"]) filename = string.resolveURI(url, metadataJson["system"]["root"])
}, 0) }, 0)
end end
@ -95,7 +98,7 @@ ent:bind( "tick", function(self)
-- eye transform -- eye transform
local flattenedTransform = nil local flattenedTransform = nil
if metadata["camera"]["settings"]["fixed"] then if fixedCamera then
flattenedTransform = transform:flatten() flattenedTransform = transform:flatten()
-- flattenedTransform.position.y = flattenedTransform.position.y -- flattenedTransform.position.y = flattenedTransform.position.y
else else
@ -121,15 +124,13 @@ ent:bind( "tick", function(self)
if timers.flashlight:elapsed() > 0.5 and keyF then if timers.flashlight:elapsed() > 0.5 and keyF then
timers.flashlight:reset() timers.flashlight:reset()
local metadata = { light = { power = light.power } } if light.metadata.power ~= light.power then
if light.entity:getComponent("Metadata")["light"]["power"] ~= light.power then light.metadata.power = light.power
metadata["light"]["power"] = light.power
light.enabled = true light.enabled = true
else else
metadata["light"]["power"] = 0 light.metadata.power = 0
light.enabled = false light.enabled = false
end end
light.entity:setComponent("Metadata", metadata)
playSound("flashlight") playSound("flashlight")
end end
@ -166,7 +167,7 @@ ent:bind( "tick", function(self)
local prop, depth = physicsState:rayCast( center, direction ) local prop, depth = physicsState:rayCast( center, direction )
if depth >= 0 and prop and not string.matched( prop:name(), "/^worldspawn/" ) then if depth >= 0 and prop and not string.matched( prop:name(), "/^worldspawn/" ) then
local heldObjectTransform = prop:getComponent("Transform") local heldObjectTransform = prop:getComponent("Transform")
local heldObjectPhysicsState = prop:getComponent("PhysicsState") local heldObjectPhysicsState = prop:getComponent("Physics")
local strength = 500 local strength = 500
local distanceSquared = (heldObjectTransform.position - flattenedTransform.position):magnitude() local distanceSquared = (heldObjectTransform.position - flattenedTransform.position):magnitude()
@ -190,7 +191,7 @@ ent:bind( "tick", function(self)
local prop = entities.get( heldObject.uid ) local prop = entities.get( heldObject.uid )
local heldObjectTransform = prop:getComponent("Transform") local heldObjectTransform = prop:getComponent("Transform")
local heldObjectPhysicsState = prop:getComponent("PhysicsState") local heldObjectPhysicsState = prop:getComponent("Physics")
if mouse1 and timers.physcannon:elapsed() > 0.5 then if mouse1 and timers.physcannon:elapsed() > 0.5 then
timers.physcannon:reset() timers.physcannon:reset()
@ -242,14 +243,14 @@ ent:addHook( "entity:Use.%UID%", function( payload )
heldObject.uid = payload.uid heldObject.uid = payload.uid
heldObject.distance = offset:norm() heldObject.distance = offset:norm()
prop:getComponent("PhysicsState"):enableGravity(false) prop:getComponent("Physics"):enableGravity(false)
else else
validUse = not string.matched( prop:name(), "/^worldspawn/" ) validUse = not string.matched( prop:name(), "/^worldspawn/" )
end end
elseif heldObject.uid ~= 0 then elseif heldObject.uid ~= 0 then
validUse = true validUse = true
local prop = entities.get( heldObject.uid ) local prop = entities.get( heldObject.uid )
local heldObjectPhysicsState = prop:getComponent("PhysicsState") local heldObjectPhysicsState = prop:getComponent("Physics")
heldObjectPhysicsState:enableGravity(true) heldObjectPhysicsState:enableGravity(true)
heldObjectPhysicsState:applyImpulse( heldObject.momentum ) heldObjectPhysicsState:applyImpulse( heldObject.momentum )

View File

@ -2,7 +2,7 @@
#include <uf/config.h> #include <uf/config.h>
#include <uf/engine/behavior/behavior.h> #include <uf/engine/behavior/behavior.h>
#include <uf/utils/serialize/serializer.h> //#include <uf/utils/serialize/serializer.h>
#include <uf/utils/memory/vector.h> #include <uf/utils/memory/vector.h>
#include <uf/utils/resolvable/resolvable.h> #include <uf/utils/resolvable/resolvable.h>
#include <uf/engine/asset/payload.h> #include <uf/engine/asset/payload.h>
@ -15,7 +15,10 @@
#define UF_ENTITY_OBJECT_UNIFIED 1 #define UF_ENTITY_OBJECT_UNIFIED 1
namespace uf { namespace uf {
class Serializer;
class UF_API Entity : public uf::Behaviors { class UF_API Entity : public uf::Behaviors {
public: public:
typedef uf::stl::vector<uf::Entity*> container_t; typedef uf::stl::vector<uf::Entity*> container_t;

View File

@ -0,0 +1,23 @@
#pragma once
#include <uf/config.h>
#if UF_USE_LUA
// agony to try and get this included within "lua.h"
#include <uf/engine/object/object.h>
namespace ext {
namespace lua {
// component shenanigans
using GetComponent = sol::object(*)(uf::Object&);
extern UF_API uf::stl::unordered_map<uf::stl::string, GetComponent> componentGetters;
template<typename T>
sol::object getComponent( uf::Object& self ) {
return sol::make_object(ext::lua::state, std::ref(self.getComponent<T>()));
}
}
}
#endif

View File

@ -6,13 +6,24 @@
#if UF_USE_LUAJIT #if UF_USE_LUAJIT
#define SOL_LUAJIT 1 #define SOL_LUAJIT 1
#endif #endif
#define SOL_NO_EXCEPTIONS 1 #define SOL_NO_EXCEPTIONS 1
#if UF_ENV_DREAMCAST #if UF_ENV_DREAMCAST
#define SOL_NO_THREAD_LOCAL 1 #define SOL_NO_THREAD_LOCAL 1
#define UF_LUA_PCALLS 0
#else #else
#define SOL_ALL_SAFETIES_ON 1 #define SOL_ALL_SAFETIES_ON 1
#define UF_LUA_PCALLS 1
#endif #endif
#if UF_LUA_PCALLS
#define LUA_FUN sol::protected_function
#else
#define LUA_FUN sol::function
#endif
#include <sol/sol.hpp> #include <sol/sol.hpp>
#include <uf/utils/memory/unordered_map.h> #include <uf/utils/memory/unordered_map.h>
#include <uf/utils/singletons/pre_main.h> #include <uf/utils/singletons/pre_main.h>
@ -37,12 +48,12 @@ namespace ext {
void UF_API terminate(); void UF_API terminate();
void UF_API onInitialization( const std::function<void()>& ); void UF_API onInitialization( const std::function<void()>& );
bool UF_API run( const uf::stl::string&, bool = true ); bool UF_API run( const uf::stl::string&, bool = UF_LUA_PCALLS );
pod::LuaScript UF_API script( const uf::stl::string& ); pod::LuaScript UF_API script( const uf::stl::string& );
void UF_API script( const uf::stl::string&, pod::LuaScript& ); void UF_API script( const uf::stl::string&, pod::LuaScript& );
bool UF_API run( const pod::LuaScript&, bool = true ); bool UF_API run( const pod::LuaScript&, bool = UF_LUA_PCALLS );
sol::table createTable(); sol::table createTable();
uf::stl::string sanitize( const uf::stl::string& dirty, int index = -1 ); uf::stl::string sanitize( const uf::stl::string& dirty, int index = -1 );
@ -52,4 +63,5 @@ namespace ext {
} }
#include "lua.inl" #include "lua.inl"
#endif #endif

View File

@ -1,4 +1,5 @@
#define UF_NS_GET_LAST(name) uf::string::replace( uf::string::split( #name, "::" ).back(), "<>", "" ) #define UF_NS_GET_LAST(name) uf::string::namespaceGetLast(#name)
#define UF_NS_REMOVE_FIRST(name) uf::string::namespaceRemoveFirst(#name)
#define TOKEN__PASTE(x, y) x ## y #define TOKEN__PASTE(x, y) x ## y
#define TOKEN_PASTE(x, y) TOKEN__PASTE(x, y) #define TOKEN_PASTE(x, y) TOKEN__PASTE(x, y)
@ -32,14 +33,32 @@ namespace {\
static uf::StaticInitialization TOKEN_PASTE(STATIC_INITIALIZATION_, __LINE__)( []{\ static uf::StaticInitialization TOKEN_PASTE(STATIC_INITIALIZATION_, __LINE__)( []{\
ext::lua::onInitialization( []{\ ext::lua::onInitialization( []{\
ext::lua::state.new_usertype<type>(UF_NS_GET_LAST(type), __VA_ARGS__);\ ext::lua::state.new_usertype<type>(UF_NS_GET_LAST(type), __VA_ARGS__);\
ext::lua::componentGetters[UF_NS_REMOVE_FIRST(type)] = &ext::lua::getComponent<type>;\
});\
});\
}
#define UF_LUA_REGISTER_COMPONENT(type, ...) \
namespace {\
static uf::StaticInitialization TOKEN_PASTE(STATIC_INITIALIZATION_, __LINE__)( []{\
ext::lua::onInitialization( []{\
ext::lua::componentGetters[UF_NS_REMOVE_FIRST(type)] = &ext::lua::getComponent<type>;\
});\
});\
}
#define UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(type, ...) \
namespace {\
static uf::StaticInitialization TOKEN_PASTE(STATIC_INITIALIZATION_, __LINE__)( []{\
ext::lua::onInitialization( []{\
ext::lua::state.new_usertype<type>(UF_NS_GET_LAST(type), __VA_ARGS__);\
ext::lua::componentGetters[UF_NS_REMOVE_FIRST(type)] = &ext::lua::getComponent<type>;\
});\ });\
});\ });\
} }
#define UF_LUA_REGISTER_USERTYPE_DEFINE(k, v) #k, v #define UF_LUA_REGISTER_USERTYPE_DEFINE(k, v) #k, v
#define UF_LUA_REGISTER_USERTYPE_MEMBER(member) UF_NS_GET_LAST(member), &member #define UF_LUA_REGISTER_USERTYPE_MEMBER(member) UF_NS_GET_LAST(member), &member
//#define UF_LUA_REGISTER_USERTYPE_MEMBER(member) UF_NS_GET_LAST(member), sol::as_function(&member)
#define UF_LUA_REGISTER_USERTYPE_MEMBER_FUN(member) UF_NS_GET_LAST(member), UF_LUA_C_FUN(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<decltype(&x), &x> #define UF_LUA_C_FUN(x) &x
#define UF_LUA_WRAP_FUN(x) sol::c_call<sol::wrap<decltype(&x), &x>> #define UF_LUA_WRAP_FUN(x) UF_LUA_C_FUN(x)

View File

@ -1,7 +1,8 @@
#define TOKEN__PASTE(x, y) x ## y #define TOKEN__PASTE(x, y) x ## y
#define TOKEN_PASTE(x, y) TOKEN__PASTE(x, y) #define TOKEN_PASTE(x, y) TOKEN__PASTE(x, y)
#define UF_NS_GET_LAST(name) uf::string::replace( uf::string::split( #name, "::" ).back(), "<>", "" ) #define UF_NS_GET_LAST(name) uf::string::namespaceGetLast(#name)
#define UF_NS_REMOVE_FIRST(name) uf::string::namespaceRemoveFirst(#name)
#define TIMER(x, ...)\ #define TIMER(x, ...)\
static bool first = true;\ static bool first = true;\

View File

@ -3,6 +3,7 @@
#include <uf/config.h> #include <uf/config.h>
#include <uf/utils/userdata/userdata.h> #include <uf/utils/userdata/userdata.h>
#define UF_LUA_SKIP_COMPONENTS
#include <uf/ext/lua/lua.h> #include <uf/ext/lua/lua.h>
#include <uf/ext/json/json.h> #include <uf/ext/json/json.h>

View File

@ -22,7 +22,10 @@ namespace uf {
uf::stl::vector<uf::stl::string> UF_API split( const uf::stl::string&, const uf::stl::string& ); uf::stl::vector<uf::stl::string> UF_API split( const uf::stl::string&, const uf::stl::string& );
uf::stl::string UF_API si( double value, const uf::stl::string& unit, size_t precision = 3 ); uf::stl::string UF_API si( double value, const uf::stl::string& unit, size_t precision = 3 );
bool UF_API contains( const uf::stl::string&, const uf::stl::string& ); bool UF_API contains( const uf::stl::string&, const uf::stl::string& );
uf::stl::vector<const char*> cStrings( const uf::stl::vector<uf::stl::string>& ); uf::stl::vector<const char*> UF_API cStrings( const uf::stl::vector<uf::stl::string>& );
uf::stl::string UF_API namespaceGetLast( const uf::stl::string& name );
uf::stl::string UF_API namespaceRemoveFirst( const uf::stl::string& name );
template<typename T> template<typename T>
uf::stl::string /*UF_API*/ join( const T&, const uf::stl::string& = "\n", bool = false ); uf::stl::string /*UF_API*/ join( const T&, const uf::stl::string& = "\n", bool = false );

View File

@ -285,15 +285,15 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
}); });
if ( metadata.ui.click.able ) { if ( metadata.clickable ) {
uf::Timer<long long> clickTimer(false); uf::Timer<long long> clickTimer(false);
clickTimer.start( uf::Time<>(-1000000) ); clickTimer.start( uf::Time<>(-1000000) );
if ( !clickTimer.running() ) clickTimer.start(); if ( !clickTimer.running() ) clickTimer.start();
this->addHook( "window:Mouse.Click", [&](pod::payloads::windowMouseClick& payload){ this->addHook( "window:Mouse.Click", [&](pod::payloads::windowMouseClick& payload){
if ( metadata.world ) return; if ( metadata.world ) return;
//if ( !metadata.box.min && !metadata.box.max ) return; //if ( !metadata.boxMin && !metadata.boxMax ) return;
if ((metadata.box.min.x > metadata.box.max.x)||(metadata.box.min.y > metadata.box.max.y)) return; if ((metadata.boxMin.x > metadata.boxMax.x)||(metadata.boxMin.y > metadata.boxMax.y)) return;
// uf::Object* manager = (uf::Object*) this->globalFindByName("Gui Manager"); // uf::Object* manager = (uf::Object*) this->globalFindByName("Gui Manager");
// pod::Vector2ui guiSize = manager ? manager->getComponent<ext::GuiManagerBehavior::Metadata>().size : pod::Vector2ui{ uf::renderer::settings::width, uf::renderer::settings::height }; // pod::Vector2ui guiSize = manager ? manager->getComponent<ext::GuiManagerBehavior::Metadata>().size : pod::Vector2ui{ uf::renderer::settings::width, uf::renderer::settings::height };
@ -316,25 +316,25 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
x = payload.mouse.position.x; x = payload.mouse.position.x;
y = payload.mouse.position.y; y = payload.mouse.position.y;
} }
clicked = ( metadata.box.min.x <= x && metadata.box.min.y <= y && metadata.box.max.x >= x && metadata.box.max.y >= y ); clicked = ( metadata.boxMin.x <= x && metadata.boxMin.y <= y && metadata.boxMax.x >= x && metadata.boxMax.y >= y );
int minX = (metadata.box.min.x * 0.5f + 0.5f) * guiSize.x; int minX = (metadata.boxMin.x * 0.5f + 0.5f) * guiSize.x;
int minY = (metadata.box.min.y * 0.5f + 0.5f) * guiSize.y; int minY = (metadata.boxMin.y * 0.5f + 0.5f) * guiSize.y;
int maxX = (metadata.box.max.x * 0.5f + 0.5f) * guiSize.x; int maxX = (metadata.boxMax.x * 0.5f + 0.5f) * guiSize.x;
int maxY = (metadata.box.max.y * 0.5f + 0.5f) * guiSize.y; int maxY = (metadata.boxMax.y * 0.5f + 0.5f) * guiSize.y;
int mouseX = payload.mouse.position.x; int mouseX = payload.mouse.position.x;
int mouseY = payload.mouse.position.y; int mouseY = payload.mouse.position.y;
} }
if ( !metadata.ui.click.ed && clicked ) { if ( !metadata.clicked && clicked ) {
this->callHook("gui:ClickStart.%UID%", payload); this->callHook("gui:ClickStart.%UID%", payload);
} else if ( metadata.ui.click.ed && !clicked ) { } else if ( metadata.clicked && !clicked ) {
this->callHook("gui:ClickEnd.%UID%", payload); this->callHook("gui:ClickEnd.%UID%", payload);
} }
metadata.ui.click.ed = clicked; metadata.clicked = clicked;
if ( clicked ) { if ( clicked ) {
this->callHook("gui:Clicked.%UID%", payload); this->callHook("gui:Clicked.%UID%", payload);
@ -381,14 +381,14 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
} }
}); });
} }
if ( metadata.ui.hover.able ) { if ( metadata.hoverable ) {
uf::Timer<long long> hoverTimer(false); uf::Timer<long long> hoverTimer(false);
hoverTimer.start( uf::Time<>(-1000000) ); hoverTimer.start( uf::Time<>(-1000000) );
this->addHook( "window:Mouse.Moved", [&](pod::payloads::windowMouseMoved& payload){ this->addHook( "window:Mouse.Moved", [&](pod::payloads::windowMouseMoved& payload){
if ( metadata.world ) return; if ( metadata.world ) return;
//if ( !metadata.box.min && !metadata.box.max ) return; //if ( !metadata.boxMin && !metadata.boxMax ) return;
if ((metadata.box.min.x > metadata.box.max.x)||(metadata.box.min.y > metadata.box.max.y)) return; if ((metadata.boxMin.x > metadata.boxMax.x)||(metadata.boxMin.y > metadata.boxMax.y)) return;
// uf::Object* manager = (uf::Object*) this->globalFindByName("Gui Manager"); // uf::Object* manager = (uf::Object*) this->globalFindByName("Gui Manager");
// pod::Vector2ui guiSize = manager ? manager->getComponent<ext::GuiManagerBehavior::Metadata>().size : pod::Vector2ui{ uf::renderer::settings::width, uf::renderer::settings::height }; // pod::Vector2ui guiSize = manager ? manager->getComponent<ext::GuiManagerBehavior::Metadata>().size : pod::Vector2ui{ uf::renderer::settings::width, uf::renderer::settings::height };
@ -405,14 +405,14 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
float x = click.x; float x = click.x;
float y = click.y; float y = click.y;
hovered = ( metadata.box.min.x <= x && metadata.box.min.y <= y && metadata.box.max.x >= x && metadata.box.max.y >= y ); hovered = ( metadata.boxMin.x <= x && metadata.boxMin.y <= y && metadata.boxMax.x >= x && metadata.boxMax.y >= y );
if ( hovered ) { if ( hovered ) {
int minX = (metadata.box.min.x * 0.5f + 0.5f) * guiSize.x; int minX = (metadata.boxMin.x * 0.5f + 0.5f) * guiSize.x;
int minY = (metadata.box.min.y * 0.5f + 0.5f) * guiSize.y; int minY = (metadata.boxMin.y * 0.5f + 0.5f) * guiSize.y;
int maxX = (metadata.box.max.x * 0.5f + 0.5f) * guiSize.x; int maxX = (metadata.boxMax.x * 0.5f + 0.5f) * guiSize.x;
int maxY = (metadata.box.max.y * 0.5f + 0.5f) * guiSize.y; int maxY = (metadata.boxMax.y * 0.5f + 0.5f) * guiSize.y;
int mouseX = payload.mouse.position.x; int mouseX = payload.mouse.position.x;
int mouseY = payload.mouse.position.y; int mouseY = payload.mouse.position.y;
@ -421,16 +421,16 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
uf::Serializer jsonPayload = ext::json::null(); uf::Serializer jsonPayload = ext::json::null();
// to-do: do something about trying to trigger json-bound hooks // to-do: do something about trying to trigger json-bound hooks
if ( !metadata.ui.hover.ed && hovered ) { if ( !metadata.hovered && hovered ) {
this->callHook("gui:HoverStart.%UID%", payload); this->callHook("gui:HoverStart.%UID%", payload);
} else if ( metadata.ui.hover.ed && !hovered ) { } else if ( metadata.hovered && !hovered ) {
this->callHook("gui:HoverEnd.%UID%", payload); this->callHook("gui:HoverEnd.%UID%", payload);
} else if ( hovered ) { /*&& hoverTimer.elapsed().asDouble() >= 1 ) { } else if ( hovered ) { /*&& hoverTimer.elapsed().asDouble() >= 1 ) {
hoverTimer.reset();*/ hoverTimer.reset();*/
this->callHook("gui:Hovered.%UID%", payload); this->callHook("gui:Hovered.%UID%", payload);
} }
metadata.ui.hover.ed = hovered; metadata.hovered = hovered;
this->callHook("gui:Mouse.Moved.%UID%", payload); this->callHook("gui:Mouse.Moved.%UID%", payload);
}); });
@ -610,10 +610,10 @@ void ext::GuiBehavior::tick( uf::Object& self ) {
max.y = std::max( max.y, translated.y ); max.y = std::max( max.y, translated.y );
} }
metadata.box.min.x = min.x; metadata.boxMin.x = min.x;
metadata.box.min.y = min.y; metadata.boxMin.y = min.y;
metadata.box.max.x = max.x; metadata.boxMax.x = max.x;
metadata.box.max.y = max.y; metadata.boxMax.y = max.y;
} }
} }
void ext::GuiBehavior::render( uf::Object& self ){} void ext::GuiBehavior::render( uf::Object& self ){}
@ -628,11 +628,11 @@ void ext::GuiBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& se
serializer["renderMode"] = /*this->*/renderMode; serializer["renderMode"] = /*this->*/renderMode;
serializer["scaling"] = /*this->*/scaleMode; serializer["scaling"] = /*this->*/scaleMode;
serializer["clickable"] = /*this->*/ui.click.able; serializer["clickable"] = /*this->*/clickable;
serializer["clicked"] = /*this->*/ui.click.ed; serializer["clicked"] = /*this->*/clicked;
serializer["hoverable"] = /*this->*/ui.hover.able; serializer["hoverable"] = /*this->*/hoverable;
serializer["hovered"] = /*this->*/ui.hover.ed; serializer["hovered"] = /*this->*/hovered;
} }
void ext::GuiBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ){ void ext::GuiBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ){
/*this->*/color = uf::vector::decode( serializer["color"], /*this->*/color ); /*this->*/color = uf::vector::decode( serializer["color"], /*this->*/color );
@ -644,7 +644,28 @@ void ext::GuiBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer&
/*this->*/renderMode = serializer["renderMode"].as( /*this->*/renderMode ); /*this->*/renderMode = serializer["renderMode"].as( /*this->*/renderMode );
/*this->*/scaleMode = serializer["scaling"].as( /*this->*/scaleMode ); /*this->*/scaleMode = serializer["scaling"].as( /*this->*/scaleMode );
/*this->*/ui.click.able = serializer["clickable"].as( /*this->*/ui.click.able ); /*this->*/clickable = serializer["clickable"].as( /*this->*/clickable );
/*this->*/ui.hover.able = serializer["hoverable"].as( /*this->*/ui.hover.able ); /*this->*/hoverable = serializer["hoverable"].as( /*this->*/hoverable );
} }
#undef this #undef this
// yikes
#include <uf/ext/lua/component.h>
UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(ext::GuiBehavior::Metadata,
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::GuiBehavior::Metadata::initialized),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::GuiBehavior::Metadata::world),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::GuiBehavior::Metadata::depth),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::GuiBehavior::Metadata::mode),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::GuiBehavior::Metadata::clickable),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::GuiBehavior::Metadata::clicked),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::GuiBehavior::Metadata::hoverable),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::GuiBehavior::Metadata::hovered),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::GuiBehavior::Metadata::size),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::GuiBehavior::Metadata::scale),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::GuiBehavior::Metadata::uv),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::GuiBehavior::Metadata::color),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::GuiBehavior::Metadata::renderMode),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::GuiBehavior::Metadata::scaleMode),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::GuiBehavior::Metadata::boxMin),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::GuiBehavior::Metadata::boxMax)
)

View File

@ -25,6 +25,11 @@ namespace ext {
float depth = 0; float depth = 0;
size_t mode = 0; size_t mode = 0;
bool clickable = false;
bool clicked = false;
bool hoverable = false;
bool hovered = false;
pod::Vector2ui size = {}; pod::Vector2ui size = {};
pod::Vector2f scale = { 1, 1 }; pod::Vector2f scale = { 1, 1 };
pod::Vector4f uv = { 0, 0, 1, 1 }; pod::Vector4f uv = { 0, 0, 1, 1 };
@ -33,17 +38,8 @@ namespace ext {
uf::stl::string renderMode = "Gui"; uf::stl::string renderMode = "Gui";
uf::stl::string scaleMode = "fixed"; uf::stl::string scaleMode = "fixed";
struct { pod::Vector2f boxMin = { 1, 1 };
struct { pod::Vector2f boxMax = { 1, 1 };
bool able = false;
bool ed = false;
} click, hover;
} ui;
struct {
pod::Vector2f min = { 1, 1 };
pod::Vector2f max = { -1, -1 };
} box;
); );
} }
} }

View File

@ -285,4 +285,15 @@ void ext::LightBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer
} }
if ( serializer["light"]["dynamic"].as<bool>() ) /*this->*/type = -/*this->*/type; if ( serializer["light"]["dynamic"].as<bool>() ) /*this->*/type = -/*this->*/type;
} }
#undef this #undef this
// yikes
#include <uf/ext/lua/component.h>
UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(ext::LightBehavior::Metadata,
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::LightBehavior::Metadata::color),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::LightBehavior::Metadata::power),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::LightBehavior::Metadata::bias),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::LightBehavior::Metadata::shadows),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::LightBehavior::Metadata::type),
UF_LUA_REGISTER_USERTYPE_MEMBER(ext::LightBehavior::Metadata::global)
)

View File

@ -1,5 +1,7 @@
#include <uf/ext/lua/lua.h> #include <uf/ext/lua/lua.h>
#if UF_USE_LUA #if UF_USE_LUA
bool ext::lua::enabled = true; bool ext::lua::enabled = true;
sol::state ext::lua::state; sol::state ext::lua::state;
uf::stl::string ext::lua::main = uf::io::root + "/scripts/main.lua"; uf::stl::string ext::lua::main = uf::io::root + "/scripts/main.lua";
@ -29,23 +31,27 @@ uf::stl::string ext::lua::sanitize( const uf::stl::string& dirty, int index ) {
return part; return part;
} }
std::optional<uf::stl::string> ext::lua::encode( sol::table table ) { std::optional<uf::stl::string> ext::lua::encode( sol::table table ) {
sol::protected_function fun = ext::lua::state["json"]["encode"]; LUA_FUN fun = ext::lua::state["json"]["encode"];
auto result = fun( table ); auto result = fun( table );
#if UF_LUA_PCALLS
if ( !result.valid() ) { if ( !result.valid() ) {
sol::error err = result; sol::error err = result;
UF_MSG_ERROR("{}", err.what()) UF_MSG_ERROR("{}", err.what())
return "{}"; return "{}";
} }
#endif
return result; return result;
} }
std::optional<sol::table> ext::lua::decode( const uf::stl::string& string ) { std::optional<sol::table> ext::lua::decode( const uf::stl::string& string ) {
sol::protected_function fun = ext::lua::state["json"]["decode"]; LUA_FUN fun = ext::lua::state["json"]["decode"];
auto result = fun( string ); auto result = fun( string );
#if UF_LUA_PCALLS
if ( !result.valid() ) { if ( !result.valid() ) {
sol::error err = result; sol::error err = result;
UF_MSG_ERROR("{}", err.what()) UF_MSG_ERROR("{}", err.what())
return createTable(); return createTable();
} }
#endif
return result; return result;
} }
@ -61,14 +67,17 @@ void ext::lua::onInitialization( const std::function<void()>& function ) {
namespace binds { namespace binds {
namespace hook { namespace hook {
void add( const uf::stl::string& name, sol::function function ) { void add( const uf::stl::string& name, LUA_FUN function ) {
uf::hooks.addHook( name, [function](ext::json::Value& json){ uf::hooks.addHook( name, [function](ext::json::Value& json){
sol::table table = ext::lua::state["json"]["decode"]( json.dump() ); sol::table table = ext::lua::state["json"]["decode"]( json.dump() );
auto result = function( table ); auto result = function( table );
// ???
#if UF_LUA_PCALLS
if ( !result.valid() ) { if ( !result.valid() ) {
sol::error err = result; sol::error err = result;
UF_MSG_ERROR("{}", err.what()) UF_MSG_ERROR("{}", err.what())
} }
#endif
}); });
}; };
void call( const uf::stl::string& name, sol::table table = ext::lua::createTable() ) { void call( const uf::stl::string& name, sol::table table = ext::lua::createTable() ) {
@ -180,7 +189,11 @@ namespace binds {
void ext::lua::initialize() { void ext::lua::initialize() {
if ( !ext::lua::enabled ) return; if ( !ext::lua::enabled ) return;
#if UF_USE_LUAJIT
state.open_libraries(sol::lib::base, sol::lib::package, sol::lib::table, sol::lib::math, sol::lib::string, sol::lib::ffi, sol::lib::jit); state.open_libraries(sol::lib::base, sol::lib::package, sol::lib::table, sol::lib::math, sol::lib::string, sol::lib::ffi, sol::lib::jit);
#else
state.open_libraries(sol::lib::base, sol::lib::package, sol::lib::table, sol::lib::math, sol::lib::string);
#endif
// load modules // load modules
for ( auto pair : modules ) { for ( auto pair : modules ) {
@ -203,36 +216,36 @@ void ext::lua::initialize() {
{ {
auto hooks = state["hooks"].get_or_create<sol::table>(); auto hooks = state["hooks"].get_or_create<sol::table>();
hooks["add"] = UF_LUA_C_FUN(::binds::hook::add); hooks.set("add", UF_LUA_C_FUN(::binds::hook::add));
hooks["call"] = UF_LUA_C_FUN(::binds::hook::call); hooks.set("call", UF_LUA_C_FUN(::binds::hook::call));
} }
// `entities` table // `entities` table
{ {
auto entities = state["entities"].get_or_create<sol::table>(); auto entities = state["entities"].get_or_create<sol::table>();
entities["get"] = UF_LUA_C_FUN(::binds::entities::get); entities.set("get", UF_LUA_C_FUN(::binds::entities::get));
entities["currentScene"] = UF_LUA_C_FUN(::binds::entities::currentScene); entities.set("currentScene", UF_LUA_C_FUN(::binds::entities::currentScene));
entities["controller"] = UF_LUA_C_FUN(::binds::entities::controller); entities.set("controller", UF_LUA_C_FUN(::binds::entities::controller));
entities["destroy"] = UF_LUA_C_FUN(::binds::entities::destroy); entities.set("destroy", UF_LUA_C_FUN(::binds::entities::destroy));
} }
// `string` table // `string` table
{ {
auto string = state["string"].get_or_create<sol::table>(); auto string = state["string"].get_or_create<sol::table>();
string["extension"] = UF_LUA_C_FUN(::binds::string::extension); string.set("extension", UF_LUA_C_FUN(::binds::string::extension));
string["resolveURI"] = UF_LUA_C_FUN(::binds::string::resolveURI); string.set("resolveURI", UF_LUA_C_FUN(::binds::string::resolveURI));
string["si"] = UF_LUA_C_FUN(::binds::string::si); string.set("si", UF_LUA_C_FUN(::binds::string::si));
string["match"] = UF_LUA_C_FUN(uf::string::match); string.set("match", UF_LUA_C_FUN(uf::string::match));
string["matched"] = UF_LUA_C_FUN(uf::string::matched); string.set("matched", UF_LUA_C_FUN(uf::string::matched));
} }
// `io` table // `io` table
{ {
auto io = state["io"].get_or_create<sol::table>(); auto io = state["io"].get_or_create<sol::table>();
io["print"] = UF_LUA_C_FUN(::binds::io::print); io.set("print", UF_LUA_C_FUN(::binds::io::print));
} }
// `math` table // `math` table
{ {
auto math = state["math"].get_or_create<sol::table>(); auto math = state["math"].get_or_create<sol::table>();
math["clamp"] = UF_LUA_C_FUN(::binds::math::clamp); math.set("clamp", UF_LUA_C_FUN(::binds::math::clamp));
} }
// `time` table // `time` table
{ {
@ -243,26 +256,27 @@ void ext::lua::initialize() {
} }
// `json` table // `json` table
{ {
state["json"]["pretty"] = UF_LUA_C_FUN(::binds::json::pretty); auto json = state["json"].get_or_create<sol::table>();
state["json"]["readFromFile"] = UF_LUA_C_FUN(::binds::json::readFromFile); json.set("pretty", UF_LUA_C_FUN(::binds::json::pretty));
state["json"]["writeToFile"] = UF_LUA_C_FUN(::binds::json::writeToFile); json.set("readFromFile", UF_LUA_C_FUN(::binds::json::readFromFile));
json.set("writeToFile", UF_LUA_C_FUN(::binds::json::writeToFile));
} }
// `window` table // `window` table
{ {
auto window = state["window"].get_or_create<sol::table>(); auto window = state["window"].get_or_create<sol::table>();
window["keyPressed"] = UF_LUA_C_FUN(uf::Window::isKeyPressed); window.set("keyPressed", UF_LUA_C_FUN(uf::Window::isKeyPressed));
} }
// `os` table // `os` table
{ {
auto os = state["os"].get_or_create<sol::table>(); auto os = state["os"].get_or_create<sol::table>();
os["arch"] = UF_LUA_C_FUN(::binds::os::arch); os.set("arch", UF_LUA_C_FUN(::binds::os::arch));
} }
// `inputs` table // `inputs` table
{ {
auto inputs = state["inputs"].get_or_create<sol::table>(); auto inputs = state["inputs"].get_or_create<sol::table>();
inputs["key"] = UF_LUA_C_FUN(uf::inputs::key); inputs.set("key", UF_LUA_C_FUN(uf::inputs::key));
inputs["analog"] = UF_LUA_C_FUN(uf::inputs::analog); inputs.set("analog", UF_LUA_C_FUN(uf::inputs::analog));
inputs["analog2"] = UF_LUA_C_FUN(uf::inputs::analog2); inputs.set("analog2", UF_LUA_C_FUN(uf::inputs::analog2));
} }
run(main); run(main);
} }

View File

@ -45,7 +45,8 @@ namespace binds {
} }
} }
UF_LUA_REGISTER_USERTYPE(uf::asset, #include <uf/ext/lua/component.h>
UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(uf::asset,
UF_LUA_REGISTER_USERTYPE_DEFINE( load, UF_LUA_C_FUN(::binds::load) ), 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( cache, UF_LUA_C_FUN(::binds::cache) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( getOriginal, UF_LUA_C_FUN(::binds::getOriginal) ) UF_LUA_REGISTER_USERTYPE_DEFINE( getOriginal, UF_LUA_C_FUN(::binds::getOriginal) )

View File

@ -1,8 +1,9 @@
#include <uf/ext/lua/lua.h>
#if 0 #if 0
#include <uf/ext/lua/lua.h>
#if UF_USE_LUA #if UF_USE_LUA
#include <uf/utils/audio/audio.h> #include <uf/utils/audio/audio.h>
UF_LUA_REGISTER_USERTYPE(uf::Audio, #include <uf/ext/lua/component.h>
UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(uf::Audio,
sol::call_constructor, sol::initializers( []( uf::Audio& self ){}, sol::call_constructor, sol::initializers( []( uf::Audio& self ){},
[]( uf::Audio& self, const uf::stl::string& filename = "", double volume = 1 ){ []( uf::Audio& self, const uf::stl::string& filename = "", double volume = 1 ){
if ( filename != "" ) self.load(filename); if ( filename != "" ) self.load(filename);

View File

@ -45,7 +45,8 @@ namespace binds {
} }
} }
UF_LUA_REGISTER_USERTYPE(uf::Camera, #include <uf/ext/lua/component.h>
UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(uf::Camera,
UF_LUA_REGISTER_USERTYPE_DEFINE( getTransform, UF_LUA_C_FUN(::binds::getTransform) ), 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( getView, UF_LUA_C_FUN(::binds::getView) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( setView, UF_LUA_C_FUN(::binds::setView) ), UF_LUA_REGISTER_USERTYPE_DEFINE( setView, UF_LUA_C_FUN(::binds::setView) ),

View File

@ -23,7 +23,8 @@ namespace binds {
} }
} }
UF_LUA_REGISTER_USERTYPE(pod::Matrix4f, #include <uf/ext/lua/component.h>
UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::Matrix4f,
sol::call_constructor, sol::initializers( sol::call_constructor, sol::initializers(
[]( pod::Matrix4f& self ) { []( pod::Matrix4f& self ) {
return self = uf::matrix::identity(); return self = uf::matrix::identity();

View File

@ -1,4 +1,5 @@
#include <uf/ext/lua/lua.h> #include <uf/ext/lua/lua.h>
#include <uf/ext/lua/component.h>
#if UF_USE_LUA #if UF_USE_LUA
#include <uf/utils/math/transform.h> #include <uf/utils/math/transform.h>
#include <uf/utils/audio/audio.h> #include <uf/utils/audio/audio.h>
@ -8,7 +9,10 @@
#include <uf/utils/math/physics.h> #include <uf/utils/math/physics.h>
#include <uf/engine/object/behaviors/lua.h> #include <uf/engine/object/behaviors/lua.h>
uf::stl::unordered_map<uf::stl::string, ext::lua::GetComponent> ext::lua::componentGetters;
namespace binds { namespace binds {
/*
namespace enums { namespace enums {
enum Components { enum Components {
Metadata, Metadata,
@ -35,10 +39,12 @@ namespace binds {
}); });
}); });
} }
*/
uf::stl::string formatHookName(uf::Object& self, const uf::stl::string n ){ uf::stl::string formatHookName(uf::Object& self, const uf::stl::string n ){
return self.formatHookName(n); return self.formatHookName(n);
} }
/*
sol::object getComponentFromEnum( uf::Object& self, binds::enums::Components type ) { sol::object getComponentFromEnum( uf::Object& self, binds::enums::Components type ) {
#define UF_LUA_RETRIEVE_COMPONENT_FROM_ENUM( E, T )\ #define UF_LUA_RETRIEVE_COMPONENT_FROM_ENUM( E, T )\
case enums::Components::E: return sol::make_object( ext::lua::state, std::ref(self.getComponent<T>()) ); case enums::Components::E: return sol::make_object( ext::lua::state, std::ref(self.getComponent<T>()) );
@ -107,9 +113,28 @@ namespace binds {
UF_LUA_UPDATE_COMPONENT(uf::Camera) UF_LUA_UPDATE_COMPONENT(uf::Camera)
UF_LUA_UPDATE_COMPONENT(pod::Physics) UF_LUA_UPDATE_COMPONENT(pod::Physics)
UF_LUA_UPDATE_COMPONENT(pod::PhysicsState) UF_LUA_UPDATE_COMPONENT(pod::PhysicsState)
} }
bool bind(uf::Object& self, const uf::stl::string& type, sol::protected_function fun ) { */
// if ( !self.hasBehavior({.type = uf::LuaBehavior::type}) ) uf::instantiator::bind( "LuaBehavior", self ); sol::object getComponent( uf::Object& self, const uf::stl::string& type ) {
if ( type == "Metadata" ) {
self.callHook( "object:Serialize.%UID%" );
auto& metadata = self.getComponent<uf::Serializer>();
auto decoded = ext::lua::decode( metadata );
if ( decoded ) {
sol::table table = decoded.value();
return sol::make_object( ext::lua::state, table );
}
UF_MSG_ERROR("Failed to deserialize metadata for {}: {}", self.getName(), self.getUid());
}
auto it = ext::lua::componentGetters.find(type);
if ( it != ext::lua::componentGetters.end() ) return it->second(self);
UF_MSG_ERROR("Invalid component of {} requested for {}", type, uf::string::toString(self));
return sol::make_object(ext::lua::state, sol::lua_nil);
}
bool bind(uf::Object& self, const uf::stl::string& type, LUA_FUN fun ) {
if ( !self.hasBehavior({.type = TYPE(uf::LuaBehavior::Metadata)}) ) uf::instantiator::bind( "LuaBehavior", self ); if ( !self.hasBehavior({.type = TYPE(uf::LuaBehavior::Metadata)}) ) uf::instantiator::bind( "LuaBehavior", self );
pod::Behavior* behaviorPointer = NULL; pod::Behavior* behaviorPointer = NULL;
auto& behaviors = self.getBehaviors(); auto& behaviors = self.getBehaviors();
@ -131,13 +156,17 @@ namespace binds {
if ( !functionPointer ) return false; if ( !functionPointer ) return false;
pod::Behavior::function_t& function = *functionPointer; pod::Behavior::function_t& function = *functionPointer;
#if !UF_LUA_PCALLS
function = fun;
#else
function = [fun]( uf::Object& s ) { function = [fun]( uf::Object& s ) {
auto result = fun(s); auto result = fun(s);
if ( !result.valid() ) { if ( !result.valid() ) {
sol::error err = result; sol::error err = result;
uf::iostream << err.what() << "\n"; UF_MSG_ERROR("{}", err.what());
} }
}; };
#endif
self.generateGraph(); self.generateGraph();
return true; return true;
} }
@ -189,16 +218,18 @@ namespace binds {
uf::Object& getParent( uf::Object& self ){ uf::Object& getParent( uf::Object& self ){
return self.getParent().as<uf::Object>(); return self.getParent().as<uf::Object>();
} }
void addHook( uf::Object& self, const uf::stl::string& name, sol::protected_function fun ) { void addHook( uf::Object& self, const uf::stl::string& name, LUA_FUN fun ) {
self.addHook( name, [fun](ext::json::Value& json){ self.addHook( name, [fun](ext::json::Value& json){
// cringe // cringe
if ( ext::json::isNull( json ) ) { if ( ext::json::isNull( json ) ) {
auto result = fun(); auto result = fun();
#if UF_LUA_PCALLS
if ( !result.valid() ) { if ( !result.valid() ) {
sol::error err = result; sol::error err = result;
uf::iostream << err.what() << "\n"; uf::iostream << err.what() << "\n";
return; return;
} }
#endif
return; return;
} }
@ -207,11 +238,13 @@ namespace binds {
if ( !decoded ) return; if ( !decoded ) return;
sol::table table = decoded.value(); sol::table table = decoded.value();
auto result = fun( table ); auto result = fun( table );
#if UF_LUA_PCALLS
if ( !result.valid() ) { if ( !result.valid() ) {
sol::error err = result; sol::error err = result;
uf::iostream << err.what() << "\n"; uf::iostream << err.what() << "\n";
return; return;
} }
#endif
}); });
} }
void callHook( uf::Object& self, const uf::stl::string& name, sol::table table = ext::lua::createTable() ) { void callHook( uf::Object& self, const uf::stl::string& name, sol::table table = ext::lua::createTable() ) {
@ -253,9 +286,10 @@ UF_LUA_REGISTER_USERTYPE(uf::Object,
UF_LUA_REGISTER_USERTYPE_DEFINE( uid, UF_LUA_C_FUN(::binds::getUid) ), 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( name, UF_LUA_C_FUN(::binds::getName) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( formatHookName, UF_LUA_C_FUN(::binds::formatHookName) ), UF_LUA_REGISTER_USERTYPE_DEFINE( formatHookName, UF_LUA_C_FUN(::binds::formatHookName) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( getComponent, UF_LUA_C_FUN(::binds::getComponentFromEnum) ), //UF_LUA_REGISTER_USERTYPE_DEFINE( getComponent, UF_LUA_C_FUN(::binds::getComponentFromEnum) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( getComponent, UF_LUA_C_FUN(::binds::getComponentFromString) ), //UF_LUA_REGISTER_USERTYPE_DEFINE( getComponent, UF_LUA_C_FUN(::binds::getComponentFromString) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( setComponent, UF_LUA_C_FUN(::binds::setComponent) ), //UF_LUA_REGISTER_USERTYPE_DEFINE( setComponent, UF_LUA_C_FUN(::binds::setComponent) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( getComponent, UF_LUA_C_FUN(::binds::getComponent) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( bind, UF_LUA_C_FUN(::binds::bind) ), 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( findByUid, UF_LUA_C_FUN(::binds::findByUid) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( findByName, UF_LUA_C_FUN(::binds::findByName) ), UF_LUA_REGISTER_USERTYPE_DEFINE( findByName, UF_LUA_C_FUN(::binds::findByName) ),
@ -272,4 +306,5 @@ UF_LUA_REGISTER_USERTYPE(uf::Object,
UF_LUA_REGISTER_USERTYPE_DEFINE( queueHook, UF_LUA_C_FUN(::binds::queueHook) ), UF_LUA_REGISTER_USERTYPE_DEFINE( queueHook, UF_LUA_C_FUN(::binds::queueHook) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, UF_LUA_C_FUN(::binds::toString) ) UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, UF_LUA_C_FUN(::binds::toString) )
) )
#endif #endif

View File

@ -27,7 +27,8 @@ namespace binds {
} }
} }
UF_LUA_REGISTER_USERTYPE(pod::Physics, #include <uf/ext/lua/component.h>
UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::Physics,
UF_LUA_REGISTER_USERTYPE_DEFINE( hasBody, UF_LUA_C_FUN(::binds::hasBody) ), UF_LUA_REGISTER_USERTYPE_DEFINE( hasBody, UF_LUA_C_FUN(::binds::hasBody) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( linearVelocity, UF_LUA_C_FUN(::binds::linearVelocity) ), UF_LUA_REGISTER_USERTYPE_DEFINE( linearVelocity, UF_LUA_C_FUN(::binds::linearVelocity) ),
UF_LUA_REGISTER_USERTYPE_DEFINE( rotationalVelocity, UF_LUA_C_FUN(::binds::rotationalVelocity) ), UF_LUA_REGISTER_USERTYPE_DEFINE( rotationalVelocity, UF_LUA_C_FUN(::binds::rotationalVelocity) ),

View File

@ -60,7 +60,8 @@ namespace binds {
} }
} }
UF_LUA_REGISTER_USERTYPE(::Quaternion, #include <uf/ext/lua/component.h>
UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(::Quaternion,
sol::call_constructor, sol::initializers( sol::call_constructor, sol::initializers(
[]( ::Quaternion& self ) { []( ::Quaternion& self ) {
return self = {0,0,0,1}; return self = {0,0,0,1};

View File

@ -11,7 +11,8 @@ namespace binds {
bool running( uf::Timer<>& self ) { return self.running(); } bool running( uf::Timer<>& self ) { return self.running(); }
} }
UF_LUA_REGISTER_USERTYPE(uf::Timer<>, #include <uf/ext/lua/component.h>
UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(uf::Timer<>,
UF_LUA_REGISTER_USERTYPE_DEFINE( elapsed, UF_LUA_C_FUN(::binds::elapsed) ), 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<>::start ),
UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Timer<>::stop ), UF_LUA_REGISTER_USERTYPE_MEMBER_FUN( uf::Timer<>::stop ),

View File

@ -49,7 +49,8 @@ namespace binds {
} }
} }
UF_LUA_REGISTER_USERTYPE(pod::Transform<>, #include <uf/ext/lua/component.h>
UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::Transform<>,
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::position), UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::position),
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::scale), UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::scale),
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::up), UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::up),

View File

@ -99,7 +99,8 @@ namespace binds {
} }
} }
UF_LUA_REGISTER_USERTYPE(pod::Vector3f, #include <uf/ext/lua/component.h>
UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::Vector3f,
sol::call_constructor, sol::initializers( sol::call_constructor, sol::initializers(
[]( pod::Vector3f& self ) { []( pod::Vector3f& self ) {
return self = pod::Vector3f{}; return self = pod::Vector3f{};
@ -132,8 +133,7 @@ UF_LUA_REGISTER_USERTYPE(pod::Vector3f,
UF_LUA_REGISTER_USERTYPE_DEFINE( dot, UF_LUA_C_FUN(::binds::v3f::dot) ), 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_DEFINE( __tostring, UF_LUA_C_FUN(::binds::v3f::toString) )
) )
/* UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::Vector4f,
UF_LUA_REGISTER_USERTYPE(pod::Vector4f,
sol::call_constructor, sol::initializers( sol::call_constructor, sol::initializers(
[]( pod::Vector4f& self ) { []( pod::Vector4f& self ) {
return self = pod::Vector4f{}; return self = pod::Vector4f{};
@ -165,5 +165,4 @@ UF_LUA_REGISTER_USERTYPE(pod::Vector4f,
UF_LUA_REGISTER_USERTYPE_DEFINE( dot, UF_LUA_C_FUN(::binds::v4f::dot) ), 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) ) UF_LUA_REGISTER_USERTYPE_DEFINE( __tostring, UF_LUA_C_FUN(::binds::v4f::toString) )
) )
*/
#endif #endif

View File

@ -4,6 +4,7 @@
#include <uf/utils/io/iostream.h> #include <uf/utils/io/iostream.h>
#include <uf/ext/zlib/zlib.h> #include <uf/ext/zlib/zlib.h>
#include <uf/ext/lua/lua.h>
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>

View File

@ -58,16 +58,6 @@ uf::stl::vector<uf::stl::string> uf::string::split( const uf::stl::string& str,
} while (pos < str.length() && prev < str.length()); } while (pos < str.length() && prev < str.length());
if ( tokens.empty() ) tokens.emplace_back(str); if ( tokens.empty() ) tokens.emplace_back(str);
return tokens; return tokens;
/*
uf::stl::vector<uf::stl::string> cont;
size_t last = 0, next = 0;
while ((next = str.find(needle, last)) != uf::stl::string::npos) {
cont.push_back(str.substr(last, next-last));
last = next + 1;
}
cont.push_back( str.substr(last) );
return cont;
*/
} }
/* /*
uf::stl::string uf::string::join( const uf::stl::vector<uf::stl::string>& strings, const uf::stl::string& delim, bool trailing ) { uf::stl::string uf::string::join( const uf::stl::vector<uf::stl::string>& strings, const uf::stl::string& delim, bool trailing ) {
@ -142,4 +132,13 @@ uf::stl::string uf::string::si( double value, const uf::stl::string& unit, size_
uf::stl::stringstream ss; uf::stl::stringstream ss;
ss << std::fixed << std::setprecision(precision) << scaled << prefix << unit; ss << std::fixed << std::setprecision(precision) << scaled << prefix << unit;
return ss.str(); return ss.str();
}
uf::stl::string uf::string::namespaceGetLast( const uf::stl::string& name ) {
return uf::string::replace( uf::string::split( name, "::" ).back(), "<>", "" );
}
uf::stl::string uf::string::namespaceRemoveFirst( const uf::stl::string& name ) {
auto split = uf::string::split( name, "::" );
split.erase(split.begin());
return uf::string::replace( uf::string::join( split, "::" ), "<>", "" );
} }