ecs refactor

This commit is contained in:
Leon van Kammen 2026-06-09 17:27:06 +02:00
parent 851aa65d6e
commit c4bb52b896
8 changed files with 147 additions and 107 deletions

View file

@ -1,24 +0,0 @@
local browser = {}
browser.to = function(url,refererer)
print("surfing to " .. url)
local URL = api.url.parse(url)
foreach( api.protocol, function(name, p)
if URL.protocol:match("^"..name) then
protocol = p
end
end)
if protocol then
local status, data, headers = protocol.request(url)
local ctx = {
succes = (status >= 200 and status < 300),
status = status,
data = data,
headers = headers,
URL = URL
}
api.exec( api.ext, 'renderURI', ctx )
end
end
return browser

32
src/ext/3DFile/main.lua Normal file
View file

@ -0,0 +1,32 @@
local api = ...
local ecs = api.ecs
return {
name = "3DFile",
enabled = true,
init = function()
modelLoader = ecs.processingSystem()
modelLoader.updatesystem = true
modelLoader.filter = ecs.requireAll('URL', 'method', 'data', 'ok')
function modelLoader:process(req, dt)
if req.ok and req.model == nil then
if req.URL.extension == 'OBJ' or
req.URL.extension == 'GLB' or
req.URL.extension == 'GLTF' then
req.model = api.graphics.newModel( api.data.newBlob(req.data) )
api.world.add({
x = 0,
y = 0,
z = 0,
model = req.model,
req = req
})
end
end
end
api.world.add(modelLoader)
end
}

38
src/ext/browser/main.lua Normal file
View file

@ -0,0 +1,38 @@
local api = ...
local ecs = api.ecs
return {
name = "browser",
enabled = true,
init = function()
urlListener = ecs.processingSystem({
updatesystem = true,
filter = ecs.requireAll('url', 'method'),
onAdd = function(self,obj)
api.ext.browser.to(obj.url, nil, obj)
end
})
api.world.add(urlListener)
end,
to = function(url,refererer, opts)
opts = opts or {method = 'GET' }
print("surfing to " .. url)
local URL = api.url.parse(url)
foreach( api.protocol, function(name, p)
if URL.protocol:match("^"..name) then
protocol = p
end
end)
if protocol then
local status, data, headers = protocol.request(url)
opts.ok = (status >= 200 and status < 300)
opts.status = status
opts.data = data
opts.headers = headers
opts.URL = URL
end
end
}

View file

@ -1,27 +0,0 @@
local api = ...
local gltf = {
name = "gltf",
enabled = true,
init = function() end,
renderURI = function(ctx)
local URL = ctx.URL
local me = api.ext.gltf
if ctx.succes and URL.extension == 'GLB' or URL.extension == 'GLTF' then
local model = api.graphics.newModel( api.data.newBlob(ctx.data) )
local ecs = api.ecs
ecs.add( ecs.world, {
x = 0,
y = 0,
z = 0,
model = model
})
end
end
}
return gltf

View file

@ -1,4 +1,5 @@
local api = ...
local ecs = api.ecs
local util = api.util
return {
@ -6,30 +7,37 @@ return {
enabled = true,
init = function()
JMLLoader = ecs.processingSystem()
JMLLoader.updatesystem = true
JMLLoader.filter = ecs.requireAll('URL', 'method', 'data', 'ok')
function JMLLoader:process(req, dt)
if req.ok and req.xml == nil then
local xml = api.parser.xml.newParser()
local xmlstr = [[
<room use_local_asset="room3">
<object id="foo.glb"/>
<object id="cube"/>
</room>
]]
util.traverseXML( xml:ParseXmlText(xmlstr), function(node,raw)
-- JML heuristic
if req.data.find("<fireboxroom>") or req.data.match("<room[ >]") then
local JML0
local JML
req.xml = api.parser.xml.newParser()
local xmlstr = req.data
-- cleanup JML0
local JML0 = xmlstr:gsub("[=%w].*<room>","<fireboxroom")
JML0 = JML0:gsub("[=%w]</room>","</room>")
util.traverseXML( req.xml:ParseXmlText(JML0), function(node,raw)
print_r(node)
end)
os.exit()
--api.world.add({
-- x = 0,
-- y = 0,
-- z = 0,
-- model = req.model,
-- req = req
--})
end
end
end
api.world.add(JMLLoader)
end,
renderURI = function(ctx)
-- TODO:
-- janusxr should be an ECS SYSTEM respond to inserted xmls
-- gltf should be a ECS SYSTEM respond to inserted objects
-- browser should insert url response to entity (respond to 404 + autodelete entity e.g.)
--
--local URL = ctx.URL
--local me = api.ext.gltf
--if ctx.succes and URL.extension == 'GLB' or URL.extension == 'GLTF' then
--end
end
}

View file

@ -9,17 +9,20 @@ return {
local ecs = api.ecs
xrfsystem = ecs.system({
filter = ecs.filter('x&y&z'),
filter = ecs.filter('x', 'y', 'z', 'model'),
onAdd = function(self,obj)
if lovr ~= nil then
xrf.traverseNodesContaining('href', obj,
xrf.makeClickable( api.ecs.worldPhysics,
function(obj, collider)
print(obj['name'] .. ".href => " .. obj['extras']['href'] )
api.ecs.add( ecs.world, {collider = collider})
api.world.add({collider = collider})
end
)
)
end
end,
onRemove = function(self,obj)
@ -27,7 +30,7 @@ return {
end
})
ecs.addSystem( ecs.world, xrfsystem )
ecs.addSystem( api.world, xrfsystem )
end
}

View file

@ -13,8 +13,11 @@ iui.resourcePath = "lovr/" .. iui.resourcePath
backend.resourcePath = "lovr/" .. backend.resourcePath
api.iui = iui
api.backend = backend
-- decorate api
api.protocol.http = require('http')
local ecs = api.ecs
-- ecs systems
local interactionsUpdater
local renderer
@ -49,7 +52,7 @@ function lovr.update(dt)
lovr.event.quit()
end
ecs.update( ecs.world, dt, ecs.filter('updatesystem') )
ecs.update( api.world, dt, ecs.filter('updatesystem') )
iui.beginFrame(dt)
@ -89,7 +92,7 @@ function lovr.draw(pass)
end
api.exec(api.ext, "draw",pass)
ecs.update( ecs.world, pass, ecs.filter('drawsystem') )
ecs.update( api.world, pass, ecs.filter('drawsystem') )
-- Dot
if selectedBox then
@ -129,7 +132,7 @@ if launch.mode == "desktop" then
function lovr.mousereleased(x, y, button)
backend.mousereleased(x, y, button)
interactionsUpdater['mouse']['released'] = {x=x, y=y, button=button}
print("ja")
print("mouserelease")
end
function lovr.wheelmoved(x, y)
@ -151,8 +154,6 @@ if launch.mode == "desktop" then
end
local initECS = function(ecs)
ecs.world = ecs.world()
-- lovr.draw => ecs.drawsystem (render-logic thread)
renderer = ecs.processingSystem()
renderer.filter = ecs.requireAny('model')
@ -169,7 +170,7 @@ local initECS = function(ecs)
1, 0, 1, 0, 0, 1)
end
end
ecs.addSystem( ecs.world, renderer )
ecs.addSystem( api.world, renderer )
-- lovr.update => ecs updatesystem (game-logic thread)
local updater = ecs.processingSystem()
@ -178,7 +179,7 @@ local initECS = function(ecs)
function updater:process(obj, dt)
print_r(obj['data'])
end
ecs.addSystem( ecs.world, updater )
ecs.addSystem( api.world, updater )
end
@ -217,7 +218,7 @@ function initInteractions(ecs)
mouse['released'] = false
mouse['pressed'] = false
end
ecs.addSystem( ecs.world, interactionsUpdater )
ecs.addSystem( api.world, interactionsUpdater )
end
initECS(api.ecs)

View file

@ -1,32 +1,41 @@
local util = require("util")
local ecs = require("tiny-ecs")
api = {
parser = {
json = require("json"),
xml = require("xmlSimple"),
},
browser = require("browser"),
url = require("url"),
util = require("util"),
ecs = require("tiny-ecs"),
ecs = ecs,
world = ecs.world(),
protocol = {},
ext = {}, -- all extensions loaded from disk at runtime
exec = function(...) util.exec(...) end -- calls function on each table item
}
if lovr ~= nil then
api = util.merge( api, lovr )
api['protocol'] = {
http = require('http')
},
util.loaddir( "ext", api, api.ext )
util.loaddir( "media", api, api.media )
require("lovr/main")
api.exec( api.ext, 'init')
end
-- convenience wrappers
api.world.add = function(...) api.ecs.add( api.world, ...) end
api.world.remove = function(...) api.ecs.remove( api.world, ...) end
local runtime
local runtimepath
if lovr ~= nil then runtime = { path = "lovr", api = lovr } end
if love ~= nil then runtime = { path = "love", api = love } end
api = util.merge( api, runtime.api )
util.loaddir( "ext", api, api.ext )
util.loaddir( "media", api, api.media )
api.exec( api.ext, 'init')
require( runtime.path .. "/main")
local url='https://coderofsalvation.codeberg.page/xrfragment-haxe/example/assets/example.glb?bar=1&f=2#foo'
--local url = 'https://codeberg.org/coderofsalvation/xrfragment/raw/branch/main/assets/template/website/website.glb'
--local url = 'https://codeberg.org/coderofsalvation/xrfragment/raw/branch/main/assets/simple-a.glb'
--local url = 'https://janusxr.org/index.html'
if lovr ~= nil then -- TODO: make this work for LOVE2D too
api.browser.to(url)
end
api.world.add({ url = url, method = 'GET' })