xurfer/src/lovr/main.lua

225 lines
5.7 KiB
Lua
Raw Normal View History

2026-06-06 12:35:31 +02:00
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
local ecs = api.ecs
2026-06-07 14:48:52 +02:00
-- ecs systems
local interactionsUpdater
local renderer
2026-06-06 12:35:31 +02:00
--- @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)
if lovr.system.isKeyDown("escape") then
lovr.event.quit()
end
2026-06-07 14:48:52 +02:00
ecs.update( ecs.world, dt, ecs.filter('updatesystem') )
2026-06-06 12:35:31 +02:00
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
2026-06-07 14:48:52 +02:00
2026-06-06 12:35:31 +02:00
api.exec(api.ext, "draw",pass)
ecs.update( ecs.world, pass, ecs.filter('drawsystem') )
2026-06-07 14:48:52 +02:00
-- 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))
2026-06-06 12:35:31 +02:00
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)
2026-06-07 14:48:52 +02:00
interactionsUpdater['mouse']['moved'] = {x=x, y=y, button=button}
2026-06-06 12:35:31 +02:00
end
function lovr.mousepressed(x, y, button)
backend.mousepressed(x, y, button)
2026-06-07 14:48:52 +02:00
interactionsUpdater['mouse']['pressed'] = {x=x, y=y, button=button}
2026-06-06 12:35:31 +02:00
end
function lovr.mousereleased(x, y, button)
backend.mousereleased(x, y, button)
2026-06-07 14:48:52 +02:00
interactionsUpdater['mouse']['released'] = {x=x, y=y, button=button}
print("ja")
2026-06-06 12:35:31 +02:00
end
function lovr.wheelmoved(x, y)
backend.wheelmoved(x, y)
2026-06-07 14:48:52 +02:00
interactionsUpdater['mouse']['wheel'] = {x=x, y=y}
2026-06-06 12:35:31 +02:00
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)
ecs.world = ecs.world()
-- lovr.draw => ecs.drawsystem (render-logic thread)
2026-06-07 14:48:52 +02:00
renderer = ecs.processingSystem()
renderer.filter = ecs.requireAny('model')
2026-06-06 12:35:31 +02:00
renderer.drawsystem = true
function renderer:process(obj, pass)
if obj['model'] ~= 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( ecs.world, renderer )
-- lovr.update => ecs updatesystem (game-logic thread)
2026-06-07 14:48:52 +02:00
local updater = ecs.processingSystem()
updater.updatesystem = true
updater.filter = ecs.requireAll('update')
function updater:process(obj, dt)
2026-06-06 12:35:31 +02:00
print_r(obj['data'])
end
2026-06-07 14:48:52 +02:00
ecs.addSystem( ecs.world, updater )
end
2026-06-06 12:35:31 +02:00
2026-06-07 14:48:52 +02:00
function initInteractions(ecs)
ecs.worldPhysics = lovr.physics.newWorld(0, 0, 0)
interactionsUpdater = ecs.processingSystem()
interactionsUpdater.updatesystem = 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( ecs.world, interactionsUpdater )
2026-06-06 12:35:31 +02:00
end
initECS(api.ecs)
2026-06-07 14:48:52 +02:00
initInteractions(api.ecs)