From c2c326f5a5fa486d8c9fd8aa9fd6badc369d0e7a Mon Sep 17 00:00:00 2001 From: Leon van Kammen Date: Fri, 12 Jun 2026 11:27:12 +0200 Subject: [PATCH] xrfragment href clickable --- src/ext/xrfragments/lovr-xrf.lua | 9 ++++--- src/ext/xrfragments/main.lua | 4 ++-- src/lovr/main.lua | 41 ++++++++++++++++++-------------- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/ext/xrfragments/lovr-xrf.lua b/src/ext/xrfragments/lovr-xrf.lua index d99e6a6..432279c 100644 --- a/src/ext/xrfragments/lovr-xrf.lua +++ b/src/ext/xrfragments/lovr-xrf.lua @@ -39,7 +39,7 @@ xrf.traverseNodesContaining = function(key,obj,cb) xrf.traverse( tree, function(node) if node['extras'] ~= nil then if node['extras'][key] ~= nil then - cb(node,obj['model'], i, metadata) + cb(node,obj, i, metadata) end end i = i + 1 @@ -82,7 +82,8 @@ xrf.calcScale = function(node) end xrf.makeClickable = function( physicsWorld, cb) - return function(node_or_mesh,model, i, metadata) + return function(node_or_mesh, obj, i, metadata) + local model = obj['model'] local node = node_or_mesh if node['mesh'] == nil then node = xrf.getNodeFromMesh(node_or_mesh, metadata, i) end print("making node " .. node['name'] .. " clickable") @@ -95,7 +96,9 @@ xrf.makeClickable = function( physicsWorld, cb) local scale = xrf.calcScale(node) -- we cannot use newMeshCollider because storage type of modelmesh is not cpu local collider = physicsWorld:newBoxCollider( - x, y, z, + x + (obj.x or 0), + y + (obj.y or 0), + z + (obj.z or 0), scale[1] * (w + 0.01), -- add 0.01 to avoid 0 scale[2] * (h + 0.01), -- in case of scale[3] * (d + 0.01) -- planes e.g. diff --git a/src/ext/xrfragments/main.lua b/src/ext/xrfragments/main.lua index a9e0764..29a081e 100644 --- a/src/ext/xrfragments/main.lua +++ b/src/ext/xrfragments/main.lua @@ -13,8 +13,8 @@ return { xrf.traverseNodesContaining('href', obj, xrf.makeClickable( api.ecs.worldPhysics, function(obj, collider) - print(obj['name'] .. ".href => " .. obj['extras']['href'] ) - api.world.add({collider = collider}) + print("\nhref was clicked: " .. obj.node.extras.href) + print_r(obj) end ) ) diff --git a/src/lovr/main.lua b/src/lovr/main.lua index fbe29ad..8b15b89 100644 --- a/src/lovr/main.lua +++ b/src/lovr/main.lua @@ -94,16 +94,16 @@ function lovr.draw(pass) ecs.update( api.world, pass, ecs.filterDraw ) -- Dot - if selectedBox then + if interactionsUpdater.selectedBox then pass:setColor(0, 0, 1) - pass:sphere(hitpoint, .01) + pass:sphere( interactionsUpdater.hitpoint, .01) end -- Laser pointer local hand = vec3(lovr.headset.getPosition('hand/left/point')) local direction = quat(lovr.headset.getOrientation('hand/left/point')):direction() pass:setColor(1, 1, 1) - pass:line(hand, selectedBox and hitpoint or (hand + direction * 50)) + pass:line(hand, interactionsUpdater.selectedBox and interactionsUpdater.hitpoint or (hand + direction * 50)) if api.mainWindow then api.mainWindow:draw(pass) @@ -120,35 +120,38 @@ end if launch.mode == "desktop" then function lovr.mousemoved(x, y, dx, dy) backend.mousemoved(x, y, dx, dy) - interactionsUpdater['mouse']['moved'] = {x=x, y=y, button=button} + interactionsUpdater.mouse.moved = {x=x, y=y, button=button} end function lovr.mousepressed(x, y, button) backend.mousepressed(x, y, button) - interactionsUpdater['mouse']['pressed'] = {x=x, y=y, button=button} + interactionsUpdater.mouse.pressed = {x=x, y=y, button=button} end function lovr.mousereleased(x, y, button) backend.mousereleased(x, y, button) - interactionsUpdater['mouse']['released'] = {x=x, y=y, button=button} + interactionsUpdater.mouse.released = {x=x, y=y, button=button} print("mouserelease") end function lovr.wheelmoved(x, y) backend.wheelmoved(x, y) - interactionsUpdater['mouse']['wheel'] = {x=x, y=y} + interactionsUpdater.mouse.wheel = {x=x, y=y} end function lovr.keypressed(key, scancode, isRepeat) backend.keypressed(key, scancode, isRepeat) + interactionsUpdater.key.pressed = {key=key,scancode=scancode,isRepeat=isRepeat} end function lovr.keyreleased(key, scancode) backend.keyreleased(key, scancode) + interactionsUpdater.key.released = {key=key,scancode=scancode,isRepeat=isRepeat} end function lovr.textinput(text) backend.textinput(text) + interactionsUpdater.input = text end end @@ -178,12 +181,14 @@ function initInteractions(ecs) ecs.worldPhysics = lovr.physics.newWorld(0, 0, 0) interactionsUpdater = ecs.processingSystem() interactionsUpdater.updatethread = true - interactionsUpdater.filter = ecs.requireAll('collider') + interactionsUpdater.filter = function(obj) return true end -- always run -- collider vars - interactionsUpdater.mouse = { released = false} + interactionsUpdater.mouse = { released = false, pressed = false, moved = false, wheel = false} + interactionsUpdater.key = { released = false, pressed = false } + interactionsUpdater.input = "" interactionsUpdater.hitpoint = lovr.math.newVec3() interactionsUpdater.selectedBox = nil - + interactionsUpdater.clear = function(o) foreach( o, function(k,v) o[k] = false end ) end function interactionsUpdater:process(obj, dt) ecs.worldPhysics:update(dt) @@ -194,19 +199,19 @@ function initInteractions(ecs) if collider then if lovr.headset.isDown(hand, 'trigger') then - local node = collider:getUserData() - selectedBox = collider - hitpoint:set(x, y, z) - print( "collide with " .. node['name'] .. " => " .. node['extras']['href'] ) print("buttondown") end if lovr.headset.wasReleased(hand, 'trigger') or interactionsUpdater['mouse']['released'] then - print('click!') + local node = collider:getUserData() + interactionsUpdater.selectedBox = collider + interactionsUpdater.hitpoint:set(x, y, z) + if node.onclick ~= nil then node.onclick(node,collider) end end end - -- reset mouse - mouse['released'] = false - mouse['pressed'] = false + -- reset stuff + interactionsUpdater.clear( interactionsUpdater.mouse ) + interactionsUpdater.clear( interactionsUpdater.key ) + interactionsUpdater.input = false end ecs.addSystem( api.world, interactionsUpdater ) end