diff --git a/xurfer.sh b/xurfer.sh index 94bb1b1..bdb2994 100755 --- a/xurfer.sh +++ b/xurfer.sh @@ -1,6 +1,8 @@ #!/bin/sh +export DEBUG=1 cd xurfer -#appimage-run ~/apps/lovr*.AppImage . test.glb -#appimage-run ~/apps/lovr*.AppImage . https://snips.sh/f/_U5-XctEVE?r=1 -#appimage-run ~/apps/lovr*.AppImage . http://localhost:8080/simple-a.glb -appimage-run ~/apps/lovr*.AppImage . http://localhost:8080/level3-4-playaudio.glb +runtime="/home/leon/apps/lovr-v0.18.0-x86_64.AppImage" +#appimage-run $runtime . test.glb +appimage-run $runtime . https://snips.sh/f/_U5-XctEVE?r=1 +#appimage-run $runtime . http://localhost:8080/simple-a.glb +#appimage-run $runtime . http://localhost:8080/level3-4-playaudio.glb diff --git a/xurfer/ecs.lua b/xurfer/ecs.lua index 9cb2f06..eec69d1 100644 --- a/xurfer/ecs.lua +++ b/xurfer/ecs.lua @@ -6,8 +6,19 @@ ecs.init = function() baseEntify.filter = ecs.rejectAll('commit') baseEntify.updatethread = true function baseEntify:onAdd(obj) + obj.commit = api.util.commit( api.world, obj, api ) api.world.commit = api.util.commit( api.world, false, api) + api.world.get = function(filter) + local found = false + foreach( api.world.entities, function(k,obj) + if type(obj) == 'table' then + if filter(obj) then found = obj end + end + end) + return found + end + end ecs.addSystem( api.world, baseEntify ) end @@ -15,7 +26,6 @@ end ecs.clear = function() api.ext.exec("onClear") api.ecs.clearEntities( api.world ) - api.ecs.update( api.world ) api.world.commit() end diff --git a/xurfer/ext/URI/main.lua b/xurfer/ext/URI/main.lua index 4b6e452..b97fbab 100644 --- a/xurfer/ext/URI/main.lua +++ b/xurfer/ext/URI/main.lua @@ -22,6 +22,7 @@ return { obj = obj or {} print("[i] loading URL: " .. URI.url) obj.URL = api.url.parse(URI.url) + trace(obj.URL) obj.URLResponse = {} local protocol = "file" foreach( api.protocol, function(name, p) @@ -33,15 +34,18 @@ return { if obj.URL.protocol == 'file' then return obj.commit('onURI') end - local status, data, headers = protocol.request(URI.url) - obj.URLResponse = { - ok = (status ~= nil and status >= 200 and status < 300), - status = status, - data = data, - headers = headers - } - api.ecs.add( api.world, obj ) - obj.commit('onURI') + protocol.request(URI.url, nil, + function(status,data,headers) + obj.URLResponse = { + ok = (status ~= nil and status >= 200 and status < 300), + status = status, + data = data, + headers = headers + } + api.ecs.add( api.world, obj ) + obj.commit('onURI') + end + ) end end diff --git a/xurfer/ext/http-lovr/main.lua b/xurfer/ext/http-lovr/main.lua new file mode 100644 index 0000000..fae7389 --- /dev/null +++ b/xurfer/ext/http-lovr/main.lua @@ -0,0 +1,76 @@ +-- this extension will make network requests run async in LoVR runtime + +local api = ... +local ecs = api.ecs + +local http +http = { + name = "http-lovr", + enabled = true, + cache = {}, + + init = function() + if lovr ~= nil then + + http.initThreadLovr() + api.protocol.http = { + request = function(url,opts,cb) + http.cache[ url ] = { url = url, opts = opts } + http.channel:push( http.cache[url] ) -- send to thread + http.cache[ url ].cb = cb -- stick callback to req + end + } + + end + end, + + initThreadLovr = function() + threadCode = [[ + local lovr = require("lovr") + require 'lovr.filesystem' + local util = require("util") + local http = require("http") + lovr.thread = require 'lovr.thread' + lovr.timer = require 'lovr.timer' + local channel = lovr.thread.getChannel('http') + while true do + local req, present = channel:peek() + if present and req.status == nil then + req.status = -1 + local status, data, headers = http.request(req.url) + req.status = status + req.data = data + req.headers = headers + channel:pop() -- remove last + channel:push(req) -- re-push but with status (which thread ignores) + lovr.timer.sleep(.1) + end + end + ]] + http.channel = lovr.thread.getChannel('http') + http.thread = lovr.thread.newThread(threadCode) + http.thread:start() + end, + + update = function() + if lovr ~= nil then + + local msg + local res, present = http.channel:peek() + if present and res.status ~= nil then + msg = http.channel:pop() + -- we got our urlrequest response + if http.cache[ msg.url ] then + http.cache[ msg.url ].cb( msg.status, msg.data, msg.headers ) + http.cache[ msg.url ] = nil + else + error("msg-object was not found in cache") + end + end + + end + end, + +} + +return http diff --git a/xurfer/ext/xrfragments/main.lua b/xurfer/ext/xrfragments/main.lua index e8b6401..e5a8ad3 100644 --- a/xurfer/ext/xrfragments/main.lua +++ b/xurfer/ext/xrfragments/main.lua @@ -19,9 +19,9 @@ xrfimpl = { trace("\n[xrf] href was clicked: " .. href) api.ext.exec("onClick", obj, collider) - --local ok = xrf.level2.load( href, obj, api.ext.URI.current, xrfimpl.onLoad) - -- or - -- xrf.level4.import( href, obj, api.ext.URI.current, xrfimpl.onImport) + local ok = xrf.level2.load( href, obj, api.ext.URI.current, xrfimpl.onLoad) + or + xrf.level4.import( href, obj, api.ext.URI.current, xrfimpl.onImport) end ) @@ -48,7 +48,16 @@ xrfimpl = { onImport = function(absoluteHref,obj) trace("[xrf.level4] ! (import) operator found") - api.ecs.add( api.world, { URI = { url = absoluteHref, method = 'GET', target = obj } }) + local filter = function(o) + return (o.URL ~= nil and o.URL.URN:gsub("#.*","") == absoluteHref:gsub("#.*","")) + end + local obj = api.world.get(filter) + if obj then + obj.URL = url.parse(absoluteHref) -- re-parse to detect media fragment change + xrfimpl.onAudioFile(obj) + else + api.ecs.add( api.world, { URI = { url = absoluteHref, method = 'GET', target = obj } }) + end end } diff --git a/xurfer/ext/xrfragments/url.lua b/xurfer/ext/xrfragments/url.lua index 3a857bc..a0fd7d6 100644 --- a/xurfer/ext/xrfragments/url.lua +++ b/xurfer/ext/xrfragments/url.lua @@ -18,6 +18,7 @@ -- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -- ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +-- -- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- -- The views and conclusions contained in the software and documentation are those of the @@ -145,14 +146,18 @@ function url.parse(url_string) return URI end -url.getAbsolute = function(href,referer) +url.getAbsolute = function(href,referer,keephash) local URL = url.parse(href) local URLref = url.parse(referer) if referer ~= nil and URL.protocol == 'file' and URLref.protocol ~= 'file' then URL.protocol = URLref.protocol URL.domain = URLref.domain URL.string = URLref.protocol .. '://' .. URLref.domain .. '/' .. URL.path .. URL.hash - URL.URN = URL.string:gsub("#.*", "") + if keephash then + URL.URN = URL.string + else + URL.URN = URL.string:gsub("#.*", "") + end end return URL end diff --git a/xurfer/lovr/main.lua b/xurfer/lovr/main.lua index bf7567d..4089329 100644 --- a/xurfer/lovr/main.lua +++ b/xurfer/lovr/main.lua @@ -14,7 +14,14 @@ backend.resourcePath = "lovr/" .. backend.resourcePath api.iui = iui api.backend = backend -- decorate api -api.protocol.http = require('http') +local http = require('http') +api.protocol.http = { + request = function(url,opts,cb) + local status, data, headers = http.request(url,opts) + if cb == nil then print("error: api.protocol.http.request called without callback") end + cb(status,data,headers) + end +} local ecs = api.ecs ecs.filterDraw = ecs.requireAll('drawthread') ecs.filterUpdate = ecs.requireAll('updatethread') @@ -49,7 +56,6 @@ function lovr.load() end function lovr.update(dt) - ecs.update( api.world, dt, ecs.filterUpdate ) iui.beginFrame(dt) diff --git a/xurfer/util.lua b/xurfer/util.lua index 1a50031..e86c390 100644 --- a/xurfer/util.lua +++ b/xurfer/util.lua @@ -117,7 +117,7 @@ function util.traverseXML( parsedXml, cb) return function() return parent end end)(parent) end - cb(struct,raw) + cb(struct,node) end, '___children' )