if os.getenv("LOCAL_LUA_DEBUGGER_VSCODE") == "1" then require "lldebugger".start() end local util = require "util" local launch = require "launch" local iui = require "lib.iui" local backend = require "lib.lovr-iui" -- modify for nested lovr path for api 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.filterDraw = ecs.requireAll('drawthread') ecs.filterUpdate = ecs.requireAll('updatethread') -- ecs systems local interactionsUpdater local renderer --- @type Texture local envTex --- @type LovrIUIWorldWindow local mainWindow function lovr.load() if launch.mode == "desktop" then backend.mouse = require "lib.lovr-mouse" lovr.system.setKeyRepeat(true) end iui.load(backend) api.exec( api.ext, "load") if iui.idiom == "vr" then lovr.headset.setPassthrough("opaque") mainWindow = backend.worldWindow.new() api.mainWindow = mainWindow end end function lovr.update(dt) ecs.update( api.world, dt, ecs.filterUpdate ) iui.beginFrame(dt) if iui.idiom == "desktop" then -- In desktop mode, we use IUI's standard window API to fill the screen. iui.beginWindow(lovr.system.getWindowDimensions()) api.exec( api.ext, "update", dt) iui.endWindow() elseif iui.idiom == "vr" then -- In VR mode, we have access to the backend's `LovrIUIWorldWindow` -- class, which handles windowing in world-space. if mainWindow:beginFrame() then iui.beginWindow(mainWindow.w, mainWindow.h) api.exec( api.ext, "update", dt) iui.endWindow() mainWindow:endFrame() end end iui.endFrame() end function lovr.draw(pass) if iui.idiom == "desktop" then backend.graphics.pass = pass iui.draw() end if api.iui.idiom == "vr" then pass:setClear(0.5, 0.5, 0.5) end api.exec(api.ext, "draw",pass) ecs.update( api.world, pass, ecs.filterDraw ) -- Dot if selectedBox then pass:setColor(0, 0, 1) pass:sphere(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)) if api.mainWindow then api.mainWindow:draw(pass) end return false end function lovr.recenter() if iui.idiom == "vr" then mainWindow:recenter() end 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} end function lovr.mousepressed(x, y, button) backend.mousepressed(x, y, 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} print("mouserelease") end function lovr.wheelmoved(x, y) backend.wheelmoved(x, y) interactionsUpdater['mouse']['wheel'] = {x=x, y=y} end function lovr.keypressed(key, scancode, isRepeat) backend.keypressed(key, scancode, isRepeat) end function lovr.keyreleased(key, scancode) backend.keyreleased(key, scancode) end function lovr.textinput(text) backend.textinput(text) end end local initECS = function(ecs) -- lovr.draw => ecs.draw (render-logic thread) renderer = ecs.processingSystem() renderer.filter = ecs.requireAll('model') renderer.drawthread = true function renderer:process(obj, pass) if obj.model ~= nil and obj.root ~= nil then pass:setMaterial() pass:setCullMode('none') pass:draw( obj['model'], obj['x'] or 0, obj['y'] or 0, obj['z'] or 0, 1, 0, 1, 0, 0, 1) end end ecs.addSystem( api.world, renderer ) end function initInteractions(ecs) ecs.worldPhysics = lovr.physics.newWorld(0, 0, 0) interactionsUpdater = ecs.processingSystem() interactionsUpdater.updatethread = true interactionsUpdater.filter = ecs.requireAll('collider') -- collider vars interactionsUpdater.mouse = { released = false} interactionsUpdater.hitpoint = lovr.math.newVec3() interactionsUpdater.selectedBox = nil function interactionsUpdater:process(obj, dt) ecs.worldPhysics:update(dt) local ox, oy, oz = lovr.headset.getPosition('hand/left/point') local dx, dy, dz = quat(lovr.headset.getOrientation('hand/left/point')):direction():mul(50):unpack() local collider, shape, x, y, z = ecs.worldPhysics:raycast(ox, oy, oz, ox + dx, oy + dy, oz + dz) 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!') end end -- reset mouse mouse['released'] = false mouse['pressed'] = false end ecs.addSystem( api.world, interactionsUpdater ) end initECS(api.ecs) initInteractions(api.ecs)