226 lines
6.5 KiB
Lua
226 lines
6.5 KiB
Lua
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 = "runtime/lovr/" .. iui.resourcePath
|
|
backend.resourcePath = "runtime/lovr/" .. backend.resourcePath
|
|
api.iui = iui
|
|
api.backend = backend
|
|
-- decorate api
|
|
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')
|
|
|
|
|
|
-- ecs systems
|
|
local interactionsUpdater
|
|
|
|
--- @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.ext.exec("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.ext.exec("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.ext.exec("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.ext.exec("draw",pass)
|
|
ecs.update( api.world, pass, ecs.filterDraw )
|
|
|
|
-- Dot
|
|
if interactionsUpdater.selectedBox then
|
|
pass:setColor(0, 0, 1)
|
|
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, interactionsUpdater.selectedBox and interactionsUpdater.hitpoint or (hand + direction * 50))
|
|
|
|
if api.mainWindow then
|
|
api.mainWindow:draw(pass)
|
|
end
|
|
return false
|
|
end
|
|
|
|
function lovr.recenter()
|
|
if iui.idiom == "vr" and lovr.headset.isActive() 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}
|
|
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)
|
|
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}
|
|
end
|
|
|
|
function lovr.textinput(text)
|
|
backend.textinput(text)
|
|
interactionsUpdater.input = text
|
|
end
|
|
end
|
|
|
|
function initInteractions(ecs)
|
|
|
|
ecs.worldPhysics = lovr.physics.newWorld(0, 0, 0)
|
|
interactionsUpdater = ecs.processingSystem()
|
|
interactionsUpdater.updatethread = true
|
|
interactionsUpdater.filter = function(obj) return true end -- always run
|
|
-- collider vars
|
|
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)
|
|
|
|
local ox, oy, oz = lovr.headset.getPosition('hand/left/point')
|
|
|
|
local direction = quat(lovr.headset.getOrientation('hand/left/point')):direction()
|
|
if direction ~= nil then
|
|
local dx, dy, dz = 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
|
|
for i, hand in ipairs(lovr.headset.getHands()) do
|
|
if lovr.headset.isDown(hand, 'trigger') then
|
|
print("buttondown")
|
|
end
|
|
if lovr.headset.wasReleased(hand, 'trigger') or interactionsUpdater['mouse']['released'] then
|
|
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
|
|
end
|
|
end
|
|
-- reset stuff
|
|
interactionsUpdater.clear( interactionsUpdater.mouse )
|
|
interactionsUpdater.clear( interactionsUpdater.key )
|
|
interactionsUpdater.input = false
|
|
end
|
|
ecs.addSystem( api.world, interactionsUpdater )
|
|
end
|
|
|
|
function initCleanups(ecs)
|
|
local navigateListener = ecs.processingSystem({
|
|
updatethread = true,
|
|
filter = ecs.requireAll('URI', ecs.rejectAll('URLResponse') ),
|
|
onAdd = function(self,obj)
|
|
-- clear colliders if needed
|
|
if obj.URI.target ~= nil and obj.URI.target == '_top' then
|
|
ecs.worldPhysics:destroy()
|
|
ecs.worldPhysics = lovr.physics.newWorld(0, 0, 0)
|
|
end
|
|
end
|
|
})
|
|
ecs.addSystem( api.world, navigateListener )
|
|
end
|
|
|
|
initInteractions(api.ecs)
|
|
initCleanups(api.ecs)
|
|
require("render/model").init(api)
|