summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.vscode/launch.json8
-rw-r--r--meta/3rd/lovr/library/lovr.audio.lua288
-rw-r--r--meta/3rd/lovr/library/lovr.data.lua92
-rw-r--r--meta/3rd/lovr/library/lovr.event.lua387
-rw-r--r--meta/3rd/lovr/library/lovr.filesystem.lua197
-rw-r--r--meta/3rd/lovr/library/lovr.graphics.lua1305
-rw-r--r--meta/3rd/lovr/library/lovr.headset.lua511
-rw-r--r--meta/3rd/lovr/library/lovr.lovr.lua15
-rw-r--r--meta/3rd/lovr/library/lovr.lua101
-rw-r--r--meta/3rd/lovr/library/lovr.math.lua147
-rw-r--r--meta/3rd/lovr/library/lovr.physics.lua142
-rw-r--r--meta/3rd/lovr/library/lovr.system.lua34
-rw-r--r--meta/3rd/lovr/library/lovr.thread.lua42
-rw-r--r--meta/3rd/lovr/library/lovr.timer.lua43
-rw-r--r--tools/build-3rd-meta.lua4
-rw-r--r--tools/love-api.lua3
-rw-r--r--tools/lovr-api.lua216
17 files changed, 3529 insertions, 6 deletions
diff --git a/.vscode/launch.json b/.vscode/launch.json
index bb14e759..671a0662 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -3,7 +3,7 @@
"version": "0.2.0",
"configurations": [
{
- "name": "đŸșæ”‹èŻ•",
+ "name": "đŸștest",
"type": "lua",
"request": "launch",
"stopOnEntry": false,
@@ -21,7 +21,7 @@
],
},
{
- "name": "附抠",
+ "name": "attach",
"type": "lua",
"request": "attach",
"stopOnEntry": false,
@@ -36,12 +36,12 @@
]
},
{
- "name": "love-api",
+ "name": "build-3rd-meta",
"type": "lua",
"request": "launch",
"stopOnEntry": false,
"luaexe": "${workspaceFolder}/bin/Windows/lua-language-server.exe",
- "program": "${workspaceRoot}/tools/love-api.lua",
+ "program": "${workspaceRoot}/tools/build-3rd-meta.lua",
"cpath": "${workspaceFolder}/bin/Windows/?.dll",
"arg": [
],
diff --git a/meta/3rd/lovr/library/lovr.audio.lua b/meta/3rd/lovr/library/lovr.audio.lua
new file mode 100644
index 00000000..269e5726
--- /dev/null
+++ b/meta/3rd/lovr/library/lovr.audio.lua
@@ -0,0 +1,288 @@
+---@meta
+
+---
+---The `lovr.audio` module is responsible for playing sound effects and music. To play a sound, create a `Source` object and call `Source:play` on it. Currently ogg, wav, and mp3 audio formats are supported.
+---
+---@class lovr.audio
+lovr.audio = {}
+
+---
+---Returns the global air absorption coefficients for the medium. This affects Sources that have the `absorption` effect enabled, causing audio volume to drop off with distance as it is absorbed by the medium it's traveling through (air, water, etc.). The difference between absorption and falloff is that absorption is more subtle and is frequency-dependent, so higher-frequency bands can get absorbed more quickly than lower ones. This can be used to apply "underwater" effects and stuff.
+---
+---@return number low # The absorption coefficient for the low frequency band.
+---@return number mid # The absorption coefficient for the mid frequency band.
+---@return number high # The absorption coefficient for the high frequency band.
+function lovr.audio.getAbsorption() end
+
+---
+---Returns a list of playback or capture devices. Each device has an `id`, `name`, and a `default` flag indicating whether it's the default device.
+---
+---To use a specific device id for playback or capture, pass it to `lovr.audio.setDevice`.
+---
+---@param type? lovr.AudioType # The type of devices to query (playback or capture).
+---@return {["[].id"]: userdata, ["[].name"]: string, ["[].default"]: boolean} devices # The list of devices.
+function lovr.audio.getDevices(type) end
+
+---
+---Returns the orientation of the virtual audio listener in angle/axis representation.
+---
+---@return number angle # The number of radians the listener is rotated around its axis of rotation.
+---@return number ax # The x component of the axis of rotation.
+---@return number ay # The y component of the axis of rotation.
+---@return number az # The z component of the axis of rotation.
+function lovr.audio.getOrientation() end
+
+---
+---Returns the position and orientation of the virtual audio listener.
+---
+---@return number x # The x position of the listener, in meters.
+---@return number y # The y position of the listener, in meters.
+---@return number z # The z position of the listener, in meters.
+---@return number angle # The number of radians the listener is rotated around its axis of rotation.
+---@return number ax # The x component of the axis of rotation.
+---@return number ay # The y component of the axis of rotation.
+---@return number az # The z component of the axis of rotation.
+function lovr.audio.getPose() end
+
+---
+---Returns the position of the virtual audio listener, in meters.
+---
+---@return number x # The x position of the listener.
+---@return number y # The y position of the listener.
+---@return number z # The z position of the listener.
+function lovr.audio.getPosition() end
+
+---
+---Returns the name of the active spatializer (`simple`, `oculus`, or `phonon`).
+---
+---The `t.audio.spatializer` setting in `lovr.conf` can be used to express a preference for a particular spatializer. If it's `nil`, all spatializers will be tried in the following order: `phonon`, `oculus`, `simple`.
+---
+---@return string spatializer # The name of the active spatializer.
+function lovr.audio.getSpatializer() end
+
+---
+---Returns the master volume. All audio sent to the playback device has its volume multiplied by this factor.
+---
+---@param units? lovr.VolumeUnit # The units to return (linear or db).
+---@return number volume # The master volume.
+function lovr.audio.getVolume(units) end
+
+---
+---Returns whether an audio device is started.
+---
+---@param type? lovr.AudioType # The type of device to check.
+---@return boolean started # Whether the device is active.
+function lovr.audio.isStarted(type) end
+
+---
+---Creates a new Source from an ogg, wav, or mp3 file.
+---
+---@overload fun(blob: lovr.Blob, options: table):lovr.Source
+---@overload fun(sound: lovr.Sound, options: table):lovr.Source
+---@param filename string # The filename of the sound to load.
+---@param options {decode: boolean, effects: table} # Optional options.
+---@return lovr.Source source # The new Source.
+function lovr.audio.newSource(filename, options) end
+
+---
+---Sets the global air absorption coefficients for the medium. This affects Sources that have the `absorption` effect enabled, causing audio volume to drop off with distance as it is absorbed by the medium it's traveling through (air, water, etc.). The difference between absorption and falloff is that absorption is more subtle and is frequency-dependent, so higher-frequency bands can get absorbed more quickly than lower ones. This can be used to apply "underwater" effects and stuff.
+---
+---@param low number # The absorption coefficient for the low frequency band.
+---@param mid number # The absorption coefficient for the mid frequency band.
+---@param high number # The absorption coefficient for the high frequency band.
+function lovr.audio.setAbsorption(low, mid, high) end
+
+---
+---Switches either the playback or capture device to a new one.
+---
+---If a device for the given type is already active, it will be stopped and destroyed. The new device will not be started automatically, use `lovr.audio.start` to start it.
+---
+---A device id (previously retrieved using `lovr.audio.getDevices`) can be given to use a specific audio device, or `nil` can be used for the id to use the default audio device.
+---
+---A sink can be also be provided when changing the device. A sink is an audio stream (`Sound` object with a `stream` type) that will receive all audio samples played (for playback) or all audio samples captured (for capture). When an audio device with a sink is started, be sure to periodically call `Sound:read` on the sink to read audio samples from it, otherwise it will overflow and discard old data. The sink can have any format, data will be converted as needed. Using a sink for the playback device will reduce performance, but this isn't the case for capture devices.
+---
+---Audio devices can be started in `shared` or `exclusive` mode. Exclusive devices may have lower latency than shared devices, but there's a higher chance that requesting exclusive access to an audio device will fail (either because it isn't supported or allowed). One strategy is to first try the device in exclusive mode, switching to shared if it doesn't work.
+---
+---@param type? lovr.AudioType # The device to switch.
+---@param id? userdata # The id of the device to use, or `nil` to use the default device.
+---@param sink? lovr.Sound # An optional audio stream to use as a sink for the device.
+---@param mode? lovr.AudioShareMode # The sharing mode for the device.
+---@return boolean success # Whether creating the audio device succeeded.
+function lovr.audio.setDevice(type, id, sink, mode) end
+
+---
+---Sets a mesh of triangles to use for modeling audio effects, using a table of vertices or a Model. When the appropriate effects are enabled, audio from `Source` objects will correctly be occluded by walls and bounce around to create realistic reverb.
+---
+---An optional `AudioMaterial` may be provided to specify the acoustic properties of the geometry.
+---
+---@overload fun(model: lovr.Model, material: lovr.AudioMaterial):boolean
+---@param vertices table # A flat table of vertices. Each vertex is 3 numbers representing its x, y, and z position. The units used for audio coordinates are up to you, but meters are recommended.
+---@param indices table # A list of indices, indicating how the vertices are connected into triangles. Indices are 1-indexed and are 32 bits (they can be bigger than 65535).
+---@param material? lovr.AudioMaterial # The acoustic material to use.
+---@return boolean success # Whether audio geometry is supported by the current spatializer and the geometry was loaded successfully.
+function lovr.audio.setGeometry(vertices, indices, material) end
+
+---
+---Sets the orientation of the virtual audio listener in angle/axis representation.
+---
+---@param angle number # The number of radians the listener should be rotated around its rotation axis.
+---@param ax number # The x component of the axis of rotation.
+---@param ay number # The y component of the axis of rotation.
+---@param az number # The z component of the axis of rotation.
+function lovr.audio.setOrientation(angle, ax, ay, az) end
+
+---
+---Sets the position and orientation of the virtual audio listener.
+---
+---@param x number # The x position of the listener, in meters.
+---@param y number # The y position of the listener, in meters.
+---@param z number # The z position of the listener, in meters.
+---@param angle number # The number of radians the listener is rotated around its axis of rotation.
+---@param ax number # The x component of the axis of rotation.
+---@param ay number # The y component of the axis of rotation.
+---@param az number # The z component of the axis of rotation.
+function lovr.audio.setPose(x, y, z, angle, ax, ay, az) end
+
+---
+---Sets the position of the virtual audio listener, in meters.
+---
+---@param x number # The x position of the listener.
+---@param y number # The y position of the listener.
+---@param z number # The z position of the listener.
+function lovr.audio.setPosition(x, y, z) end
+
+---
+---Sets the master volume. All audio sent to the playback device has its volume multiplied by this factor.
+---
+---@param volume number # The master volume.
+---@param units? lovr.VolumeUnit # The units of the value.
+function lovr.audio.setVolume(volume, units) end
+
+---
+---Starts the active playback or capture device. By default the playback device is initialized and started, but this can be controlled using the `t.audio.start` flag in `lovr.conf`.
+---
+---@param type? lovr.AudioType # The type of device to start.
+---@return boolean started # Whether the device was successfully started.
+function lovr.audio.start(type) end
+
+---
+---Stops the active playback or capture device. This may fail if:
+---
+---- The device is not started
+---- No device was initialized with `lovr.audio.setDevice`
+---
+---@param type? lovr.AudioType # The type of device to stop.
+---@return boolean stopped # Whether the device was successfully stopped.
+function lovr.audio.stop(type) end
+
+---
+---Different types of audio material presets, for use with `lovr.audio.setGeometry`.
+---
+---@class lovr.AudioMaterial
+---
+---Generic default audio material.
+---
+---@field generic integer
+---
+---Brick.
+---
+---@field brick integer
+---
+---Carpet.
+---
+---@field carpet integer
+---
+---Ceramic.
+---
+---@field ceramic integer
+---
+---Concrete.
+---
+---@field concrete integer
+---@field glass integer
+---@field gravel integer
+---@field metal integer
+---@field plaster integer
+---@field rock integer
+---@field wood integer
+
+---
+---Audio devices can be created in shared mode or exclusive mode. In exclusive mode, the audio device is the only one active on the system, which gives better performance and lower latency. However, exclusive devices aren't always supported and might not be allowed, so there is a higher chance that creating one will fail.
+---
+---@class lovr.AudioShareMode
+---
+---Shared mode.
+---
+---@field shared integer
+---
+---Exclusive mode.
+---
+---@field exclusive integer
+
+---
+---When referencing audio devices, this indicates whether it's the playback or capture device.
+---
+---@class lovr.AudioType
+---
+---The playback device (speakers, headphones).
+---
+---@field playback integer
+---
+---The capture device (microphone).
+---
+---@field capture integer
+
+---
+---Different types of effects that can be applied with `Source:setEffectEnabled`.
+---
+---@class lovr.Effect
+---
+---Models absorption as sound travels through the air, water, etc.
+---
+---@field absorption integer
+---
+---Decreases audio volume with distance (1 / max(distance, 1)).
+---
+---@field falloff integer
+---
+---Causes audio to drop off when the Source is occluded by geometry.
+---
+---@field occlusion integer
+---
+---Models reverb caused by audio bouncing off of geometry.
+---
+---@field reverb integer
+---
+---Spatializes the Source using either simple panning or an HRTF.
+---
+---@field spatialization integer
+---
+---Causes audio to be heard through walls when occluded, based on audio materials.
+---
+---@field transmission integer
+
+---
+---When figuring out how long a Source is or seeking to a specific position in the sound file, units can be expressed in terms of seconds or in terms of frames. A frame is one set of samples for each channel (one sample for mono, two samples for stereo).
+---
+---@class lovr.TimeUnit
+---
+---Seconds.
+---
+---@field seconds integer
+---
+---Frames.
+---
+---@field frames integer
+
+---
+---When accessing the volume of Sources or the audio listener, this can be done in linear units with a 0 to 1 range, or in decibels with a range of -∞ to 0.
+---
+---@class lovr.VolumeUnit
+---
+---Linear volume range.
+---
+---@field linear integer
+---
+---Decibels.
+---
+---@field db integer
diff --git a/meta/3rd/lovr/library/lovr.data.lua b/meta/3rd/lovr/library/lovr.data.lua
new file mode 100644
index 00000000..a3e75bea
--- /dev/null
+++ b/meta/3rd/lovr/library/lovr.data.lua
@@ -0,0 +1,92 @@
+---@meta
+
+---
+---The `lovr.data` module provides functions for accessing underlying data representations for several LÖVR objects.
+---
+---@class lovr.data
+lovr.data = {}
+
+---
+---Creates a new Blob.
+---
+---@overload fun(contents: string, name: string):lovr.Blob
+---@overload fun(source: lovr.Blob, name: string):lovr.Blob
+---@param size number # The amount of data to allocate for the Blob, in bytes. All of the bytes will be filled with zeroes.
+---@param name? string # A name for the Blob (used in error messages)
+---@return lovr.Blob blob # The new Blob.
+function lovr.data.newBlob(size, name) end
+
+---
+---Creates a new Image. Image data can be loaded and decoded from an image file, or a raw block of pixels with a specified width, height, and format can be created.
+---
+---@overload fun(width: number, height: number, format: lovr.TextureFormat, data: lovr.Blob):lovr.Image
+---@overload fun(source: lovr.Image):lovr.Image
+---@overload fun(blob: lovr.Blob, flip: boolean):lovr.Image
+---@param filename string # The filename of the image to load.
+---@param flip? boolean # Whether to vertically flip the image on load. This should be true for normal textures, and false for textures that are going to be used in a cubemap.
+---@return lovr.Image image # The new Image.
+function lovr.data.newImage(filename, flip) end
+
+---
+---Loads a 3D model from a file. The supported 3D file formats are OBJ and glTF.
+---
+---@overload fun(blob: lovr.Blob):lovr.ModelData
+---@param filename string # The filename of the model to load.
+---@return lovr.ModelData modelData # The new ModelData.
+function lovr.data.newModelData(filename) end
+
+---
+---Creates a new Rasterizer from a TTF file.
+---
+---@overload fun(filename: string, size: number):lovr.Rasterizer
+---@overload fun(blob: lovr.Blob, size: number):lovr.Rasterizer
+---@param size? number # The resolution to render the fonts at, in pixels. Higher resolutions use more memory and processing power but may provide better quality results for some fonts/situations.
+---@return lovr.Rasterizer rasterizer # The new Rasterizer.
+function lovr.data.newRasterizer(size) end
+
+---
+---Creates a new Sound. A sound can be loaded from an audio file, or it can be created empty with capacity for a certain number of audio frames.
+---
+---When loading audio from a file, use the `decode` option to control whether compressed audio should remain compressed or immediately get decoded to raw samples.
+---
+---When creating an empty sound, the `contents` parameter can be set to `'stream'` to create an audio stream. On streams, `Sound:setFrames` will always write to the end of the stream, and `Sound:getFrames` will always read the oldest samples from the beginning. The number of frames in the sound is the total capacity of the stream's buffer.
+---
+---@overload fun(filename: string, decode: boolean):lovr.Sound
+---@overload fun(blob: lovr.Blob, decode: boolean):lovr.Sound
+---@param frames number # The number of frames the Sound can hold.
+---@param format? lovr.SampleFormat # The sample data type.
+---@param channels? lovr.ChannelLayout # The channel layout.
+---@param sampleRate? number # The sample rate, in Hz.
+---@param contents? lovr.* # A Blob containing raw audio samples to use as the initial contents, 'stream' to create an audio stream, or `nil` to leave the data initialized to zero.
+---@return lovr.Sound sound # Sounds good.
+function lovr.data.newSound(frames, format, channels, sampleRate, contents) end
+
+---
+---Sounds can have different numbers of channels, and those channels can map to various speaker layouts.
+---
+---@class lovr.ChannelLayout
+---
+---1 channel.
+---
+---@field mono integer
+---
+---2 channels. The first channel is for the left speaker and the second is for the right.
+---
+---@field stereo integer
+---
+---4 channels. Ambisonic channels don't map directly to speakers but instead represent directions in 3D space, sort of like the images of a skybox. Currently, ambisonic sounds can only be loaded, not played.
+---
+---@field ambisonic integer
+
+---
+---Sounds can store audio samples as 16 bit integers or 32 bit floats.
+---
+---@class lovr.SampleFormat
+---
+---32 bit floating point samples (between -1.0 and 1.0).
+---
+---@field f32 integer
+---
+---16 bit integer samples (between -32768 and 32767).
+---
+---@field i16 integer
diff --git a/meta/3rd/lovr/library/lovr.event.lua b/meta/3rd/lovr/library/lovr.event.lua
new file mode 100644
index 00000000..416d955f
--- /dev/null
+++ b/meta/3rd/lovr/library/lovr.event.lua
@@ -0,0 +1,387 @@
+---@meta
+
+---
+---The `lovr.event` module handles events from the operating system.
+---
+---Due to its low-level nature, it's rare to use `lovr.event` in simple projects.
+---
+---@class lovr.event
+lovr.event = {}
+
+---
+---Clears the event queue, removing any unprocessed events.
+---
+function lovr.event.clear() end
+
+---
+---This function returns a Lua iterator for all of the unprocessed items in the event queue. Each event consists of a name as a string, followed by event-specific arguments. This function is called in the default implementation of `lovr.run`, so it is normally not necessary to poll for events yourself.
+---
+---@return function iterator # The iterator function, usable in a for loop.
+function lovr.event.poll() end
+
+---
+---Fills the event queue with unprocessed events from the operating system. This function should be called often, otherwise the operating system will consider the application unresponsive. This function is called in the default implementation of `lovr.run`.
+---
+function lovr.event.pump() end
+
+---
+---Pushes an event onto the event queue. It will be processed the next time `lovr.event.poll` is called. For an event to be processed properly, there needs to be a function in the `lovr.handlers` table with a key that's the same as the event name.
+---
+---@param name string # The name of the event.
+function lovr.event.push(name) end
+
+---
+---Pushes an event to quit. An optional number can be passed to set the exit code for the application. An exit code of zero indicates normal termination, whereas a nonzero exit code indicates that an error occurred.
+---
+---@param code? number # The exit code of the program.
+function lovr.event.quit(code) end
+
+---
+---Pushes an event to restart the framework.
+---
+function lovr.event.restart() end
+
+---
+---Keys that can be pressed on a keyboard. Notably, numpad keys are missing right now.
+---
+---@class lovr.KeyCode
+---
+---The A key.
+---
+---@field a integer
+---
+---The B key.
+---
+---@field b integer
+---
+---The C key.
+---
+---@field c integer
+---
+---The D key.
+---
+---@field d integer
+---
+---The E key.
+---
+---@field e integer
+---
+---The F key.
+---
+---@field f integer
+---
+---The G key.
+---
+---@field g integer
+---
+---The H key.
+---
+---@field h integer
+---
+---The I key.
+---
+---@field i integer
+---
+---The J key.
+---
+---@field j integer
+---
+---The K key.
+---
+---@field k integer
+---
+---The L key.
+---
+---@field l integer
+---
+---The M key.
+---
+---@field m integer
+---
+---The N key.
+---
+---@field n integer
+---
+---The O key.
+---
+---@field o integer
+---
+---The P key.
+---
+---@field p integer
+---
+---The Q key.
+---
+---@field q integer
+---
+---The R key.
+---
+---@field r integer
+---
+---The S key.
+---
+---@field s integer
+---
+---The T key.
+---
+---@field t integer
+---
+---The U key.
+---
+---@field u integer
+---
+---The V key.
+---
+---@field v integer
+---
+---The W key.
+---
+---@field w integer
+---
+---The X key.
+---
+---@field x integer
+---
+---The Y key.
+---
+---@field y integer
+---
+---The Z key.
+---
+---@field z integer
+---
+---The 0 key.
+---
+---@field ["0"] integer
+---
+---The 1 key.
+---
+---@field ["1"] integer
+---
+---The 2 key.
+---
+---@field ["2"] integer
+---
+---The 3 key.
+---
+---@field ["3"] integer
+---
+---The 4 key.
+---
+---@field ["4"] integer
+---
+---The 5 key.
+---
+---@field ["5"] integer
+---
+---The 6 key.
+---
+---@field ["6"] integer
+---
+---The 7 key.
+---
+---@field ["7"] integer
+---
+---The 8 key.
+---
+---@field ["8"] integer
+---
+---The 9 key.
+---
+---@field ["9"] integer
+---
+---The space bar.
+---
+---@field space integer
+---
+---The enter key.
+---
+---@field return integer
+---
+---The tab key.
+---
+---@field tab integer
+---
+---The escape key.
+---
+---@field escape integer
+---
+---The backspace key.
+---
+---@field backspace integer
+---
+---The up arrow key.
+---
+---@field up integer
+---
+---The down arrow key.
+---
+---@field down integer
+---
+---The left arrow key.
+---
+---@field left integer
+---
+---The right arrow key.
+---
+---@field right integer
+---
+---The home key.
+---
+---@field home integer
+---
+---The end key.
+---
+---@field end integer
+---
+---The page up key.
+---
+---@field pageup integer
+---
+---The page down key.
+---
+---@field pagedown integer
+---
+---The insert key.
+---
+---@field insert integer
+---
+---The delete key.
+---
+---@field delete integer
+---
+---The F1 key.
+---
+---@field f1 integer
+---
+---The F2 key.
+---
+---@field f2 integer
+---
+---The F3 key.
+---
+---@field f3 integer
+---
+---The F4 key.
+---
+---@field f4 integer
+---
+---The F5 key.
+---
+---@field f5 integer
+---
+---The F6 key.
+---
+---@field f6 integer
+---
+---The F7 key.
+---
+---@field f7 integer
+---
+---The F8 key.
+---
+---@field f8 integer
+---
+---The F9 key.
+---
+---@field f9 integer
+---
+---The F10 key.
+---
+---@field f10 integer
+---
+---The F11 key.
+---
+---@field f11 integer
+---
+---The F12 key.
+---
+---@field f12 integer
+---
+---The backtick/backquote/grave accent key.
+---
+---@field ["`"] integer
+---
+---The dash/hyphen/minus key.
+---
+---@field ["-"] integer
+---
+---The equal sign key.
+---
+---@field ["="] integer
+---
+---The left bracket key.
+---
+---@field ["["] integer
+---
+---The right bracket key.
+---
+---@field ["]"] integer
+---
+---The backslash key.
+---
+---@field ["\\"] integer
+---
+---The semicolon key.
+---
+---@field [";"] integer
+---
+---The single quote key.
+---
+---@field ["'"] integer
+---
+---The comma key.
+---
+---@field [","] integer
+---
+---The period key.
+---
+---@field ["."] integer
+---
+---The slash key.
+---
+---@field ["/"] integer
+---
+---The left control key.
+---
+---@field lctrl integer
+---
+---The left shift key.
+---
+---@field lshift integer
+---
+---The left alt key.
+---
+---@field lalt integer
+---
+---The left OS key (windows, command, super).
+---
+---@field lgui integer
+---
+---The right control key.
+---
+---@field rctrl integer
+---
+---The right shift key.
+---
+---@field rshift integer
+---
+---The right alt key.
+---
+---@field ralt integer
+---
+---The right OS key (windows, command, super).
+---
+---@field rgui integer
+---
+---The caps lock key.
+---
+---@field capslock integer
+---
+---The scroll lock key.
+---
+---@field scrolllock integer
+---
+---The numlock key.
+---
+---@field numlock integer
diff --git a/meta/3rd/lovr/library/lovr.filesystem.lua b/meta/3rd/lovr/library/lovr.filesystem.lua
new file mode 100644
index 00000000..37fe8e0e
--- /dev/null
+++ b/meta/3rd/lovr/library/lovr.filesystem.lua
@@ -0,0 +1,197 @@
+---@meta
+
+---
+---The `lovr.filesystem` module provides access to the filesystem.
+---
+---@class lovr.filesystem
+lovr.filesystem = {}
+
+---
+---Appends content to the end of a file.
+---
+---@overload fun(filename: string, blob: lovr.Blob):number
+---@param filename string # The file to append to.
+---@param content string # A string to write to the end of the file.
+---@return number bytes # The number of bytes actually appended to the file.
+function lovr.filesystem.append(filename, content) end
+
+---
+---Creates a directory in the save directory. Any parent directories that don't exist will also be created.
+---
+---@param path string # The directory to create, recursively.
+---@return boolean success # Whether the directory was created.
+function lovr.filesystem.createDirectory(path) end
+
+---
+---Returns the application data directory. This will be something like:
+---
+---- `C:\Users\user\AppData\Roaming` on Windows.
+---- `/home/user/.config` on Linux.
+---- `/Users/user/Library/Application Support` on macOS.
+---
+---@return string path # The absolute path to the appdata directory.
+function lovr.filesystem.getAppdataDirectory() end
+
+---
+---Returns a sorted table containing all files and folders in a single directory.
+---
+---@param path string # The directory.
+---@return lovr.items table # A table with a string for each file and subfolder in the directory.
+function lovr.filesystem.getDirectoryItems(path) end
+
+---
+---Returns the absolute path of the LÖVR executable.
+---
+---@return string path # The absolute path of the LÖVR executable, or `nil` if it is unknown.
+function lovr.filesystem.getExecutablePath() end
+
+---
+---Returns the identity of the game, which is used as the name of the save directory. The default is `default`. It can be changed using `t.identity` in `lovr.conf`.
+---
+---@return string identity # The name of the save directory, or `nil` if it isn't set.
+function lovr.filesystem.getIdentity() end
+
+---
+---Returns when a file was last modified, since some arbitrary time in the past.
+---
+---@param path string # The file to check.
+---@return number time # The modification time of the file, in seconds, or `nil` if it's unknown.
+function lovr.filesystem.getLastModified(path) end
+
+---
+---Get the absolute path of the mounted archive containing a path in the virtual filesystem. This can be used to determine if a file is in the game's source directory or the save directory.
+---
+---@param path string # The path to check.
+---@return string realpath # The absolute path of the mounted archive containing `path`.
+function lovr.filesystem.getRealDirectory(path) end
+
+---
+---Returns the require path. The require path is a semicolon-separated list of patterns that LÖVR will use to search for files when they are `require`d. Any question marks in the pattern will be replaced with the module that is being required. It is similar to Lua\'s `package.path` variable, but the main difference is that the patterns are relative to the virtual filesystem.
+---
+---@return string path # The semicolon separated list of search patterns.
+function lovr.filesystem.getRequirePath() end
+
+---
+---Returns the absolute path to the save directory.
+---
+---@return string path # The absolute path to the save directory.
+function lovr.filesystem.getSaveDirectory() end
+
+---
+---Returns the size of a file, in bytes.
+---
+---@param file string # The file.
+---@return number size # The size of the file, in bytes.
+function lovr.filesystem.getSize(file) end
+
+---
+---Get the absolute path of the project's source directory or archive.
+---
+---@return string path # The absolute path of the project's source, or `nil` if it's unknown.
+function lovr.filesystem.getSource() end
+
+---
+---Returns the absolute path of the user's home directory.
+---
+---@return string path # The absolute path of the user's home directory.
+function lovr.filesystem.getUserDirectory() end
+
+---
+---Returns the absolute path of the working directory. Usually this is where the executable was started from.
+---
+---@return string path # The current working directory, or `nil` if it's unknown.
+function lovr.filesystem.getWorkingDirectory() end
+
+---
+---Check if a path exists and is a directory.
+---
+---@param path string # The path to check.
+---@return boolean isDirectory # Whether or not the path is a directory.
+function lovr.filesystem.isDirectory(path) end
+
+---
+---Check if a path exists and is a file.
+---
+---@param path string # The path to check.
+---@return boolean isFile # Whether or not the path is a file.
+function lovr.filesystem.isFile(path) end
+
+---
+---Returns whether the current project source is fused to the executable.
+---
+---@return boolean fused # Whether or not the project is fused.
+function lovr.filesystem.isFused() end
+
+---
+---Load a file containing Lua code, returning a Lua chunk that can be run.
+---
+---@param filename string # The file to load.
+---@return function chunk # The runnable chunk.
+function lovr.filesystem.load(filename) end
+
+---
+---Mounts a directory or `.zip` archive, adding it to the virtual filesystem. This allows you to read files from it.
+---
+---@param path string # The path to mount.
+---@param mountpoint? string # The path in the virtual filesystem to mount to.
+---@param append? boolean # Whether the archive will be added to the end or the beginning of the search path.
+---@param root? string # A subdirectory inside the archive to use as the root. If `nil`, the actual root of the archive is used.
+---@return boolean success # Whether the archive was successfully mounted.
+function lovr.filesystem.mount(path, mountpoint, append, root) end
+
+---
+---Creates a new Blob that contains the contents of a file.
+---
+---@param filename string # The file to load.
+---@return lovr.Blob blob # The new Blob.
+function lovr.filesystem.newBlob(filename) end
+
+---
+---Read the contents of a file.
+---
+---@param filename string # The name of the file to read.
+---@param bytes? number # The number of bytes to read (if -1, all bytes will be read).
+---@return string contents # The contents of the file.
+---@return number bytes # The number of bytes read from the file.
+function lovr.filesystem.read(filename, bytes) end
+
+---
+---Remove a file or directory in the save directory.
+---
+---@param path string # The file or directory to remove.
+---@return boolean success # Whether the path was removed.
+function lovr.filesystem.remove(path) end
+
+---
+---Set the name of the save directory.
+---
+---@param identity string # The new name of the save directory.
+function lovr.filesystem.setIdentity(identity) end
+
+---
+---Sets the require path. The require path is a semicolon-separated list of patterns that LÖVR will use to search for files when they are `require`d. Any question marks in the pattern will be replaced with the module that is being required. It is similar to Lua\'s `package.path` variable, but the main difference is that the patterns are relative to the save directory and the project directory.
+---
+---@param path? string # An optional semicolon separated list of search patterns.
+function lovr.filesystem.setRequirePath(path) end
+
+---
+---Sets the location of the project's source. This can only be done once, and is usually done internally.
+---
+---@param identity string # The path containing the project's source.
+function lovr.filesystem.setSource(identity) end
+
+---
+---Unmounts a directory or archive previously mounted with `lovr.filesystem.mount`.
+---
+---@param path string # The path to unmount.
+---@return boolean success # Whether the archive was unmounted.
+function lovr.filesystem.unmount(path) end
+
+---
+---Write to a file.
+---
+---@overload fun(filename: string, blob: lovr.Blob):number
+---@param filename string # The file to write to.
+---@param content string # A string to write to the file.
+---@return number bytes # The number of bytes written.
+function lovr.filesystem.write(filename, content) end
diff --git a/meta/3rd/lovr/library/lovr.graphics.lua b/meta/3rd/lovr/library/lovr.graphics.lua
new file mode 100644
index 00000000..930c01f5
--- /dev/null
+++ b/meta/3rd/lovr/library/lovr.graphics.lua
@@ -0,0 +1,1305 @@
+---@meta
+
+---
+---The `lovr.graphics` module renders graphics to displays. Anything rendered using this module will automatically show up in the VR headset if one is connected, otherwise it will just show up in a window on the desktop.
+---
+---@class lovr.graphics
+lovr.graphics = {}
+
+---
+---Draws an arc.
+---
+---@overload fun(material: lovr.Material, x: number, y: number, z: number, radius: number, angle: number, ax: number, ay: number, az: number, start: number, end: number, segments: number)
+---@overload fun(mode: lovr.DrawStyle, transform: lovr.mat4, start: number, end: number, segments: number)
+---@overload fun(material: lovr.Material, transform: lovr.mat4, start: number, end: number, segments: number)
+---@overload fun(mode: lovr.DrawStyle, arcmode: lovr.ArcMode, x: number, y: number, z: number, radius: number, angle: number, ax: number, ay: number, az: number, start: number, end: number, segments: number)
+---@overload fun(material: lovr.Material, arcmode: lovr.ArcMode, x: number, y: number, z: number, radius: number, angle: number, ax: number, ay: number, az: number, start: number, end: number, segments: number)
+---@overload fun(mode: lovr.DrawStyle, arcmode: lovr.ArcMode, transform: lovr.mat4, start: number, end: number, segments: number)
+---@overload fun(material: lovr.Material, arcmode: lovr.ArcMode, transform: lovr.mat4, start: number, end: number, segments: number)
+---@param mode lovr.DrawStyle # Whether the arc is filled or outlined.
+---@param x? number # The x coordinate of the center of the arc.
+---@param y? number # The y coordinate of the center of the arc.
+---@param z? number # The z coordinate of the center of the arc.
+---@param radius? number # The radius of the arc, in meters.
+---@param angle? number # The rotation of the arc around its rotation axis, in radians.
+---@param ax? number # The x coordinate of the arc's axis of rotation.
+---@param ay? number # The y coordinate of the arc's axis of rotation.
+---@param az? number # The z coordinate of the arc's axis of rotation.
+---@param start? number # The starting angle of the arc, in radians.
+---@param end? number # The ending angle of the arc, in radians.
+---@param segments? number # The number of segments to use for the full circle. A smaller number of segments will be used, depending on how long the arc is.
+function lovr.graphics.arc(mode, x, y, z, radius, angle, ax, ay, az, start, end, segments) end
+
+---
+---Draws a box. This is similar to `lovr.graphics.cube` except you can have different values for the width, height, and depth of the box.
+---
+---@overload fun(material: lovr.Material, x: number, y: number, z: number, width: number, height: number, depth: number, angle: number, ax: number, ay: number, az: number)
+---@overload fun(mode: lovr.DrawStyle, transform: lovr.mat4)
+---@overload fun(material: lovr.Material, transform: lovr.mat4)
+---@param mode lovr.DrawStyle # How to draw the box.
+---@param x? number # The x coordinate of the center of the box.
+---@param y? number # The y coordinate of the center of the box.
+---@param z? number # The z coordinate of the center of the box.
+---@param width? number # The width of the box, in meters.
+---@param height? number # The height of the box, in meters.
+---@param depth? number # The depth of the box, in meters.
+---@param angle? number # The rotation of the box around its rotation axis, in radians.
+---@param ax? number # The x coordinate of the axis of rotation.
+---@param ay? number # The y coordinate of the axis of rotation.
+---@param az? number # The z coordinate of the axis of rotation.
+function lovr.graphics.box(mode, x, y, z, width, height, depth, angle, ax, ay, az) end
+
+---
+---Draws a 2D circle.
+---
+---@overload fun(material: lovr.Material, x: number, y: number, z: number, radius: number, angle: number, ax: number, ay: number, az: number, segments: number)
+---@overload fun(mode: lovr.DrawStyle, transform: lovr.mat4, segments: number)
+---@overload fun(material: lovr.Material, transform: lovr.mat4, segments: number)
+---@param mode lovr.DrawStyle # Whether the circle is filled or outlined.
+---@param x? number # The x coordinate of the center of the circle.
+---@param y? number # The y coordinate of the center of the circle.
+---@param z? number # The z coordinate of the center of the circle.
+---@param radius? number # The radius of the circle, in meters.
+---@param angle? number # The rotation of the circle around its rotation axis, in radians.
+---@param ax? number # The x coordinate of the circle's axis of rotation.
+---@param ay? number # The y coordinate of the circle's axis of rotation.
+---@param az? number # The z coordinate of the circle's axis of rotation.
+---@param segments? number # The number of segments to use for the circle geometry. Higher numbers increase smoothness but increase rendering cost slightly.
+function lovr.graphics.circle(mode, x, y, z, radius, angle, ax, ay, az, segments) end
+
+---
+---Clears the screen, resetting the color, depth, and stencil information to default values. This function is called automatically by `lovr.run` at the beginning of each frame to clear out the data from the previous frame.
+---
+---@overload fun(r: number, g: number, b: number, a: number, z: number, s: number)
+---@overload fun(hex: number)
+---@param color? boolean # Whether or not to clear color information on the screen.
+---@param depth? boolean # Whether or not to clear the depth information on the screen.
+---@param stencil? boolean # Whether or not to clear the stencil information on the screen.
+function lovr.graphics.clear(color, depth, stencil) end
+
+---
+---This function runs a compute shader on the GPU. Compute shaders must be created with `lovr.graphics.newComputeShader` and they should implement the `void compute();` GLSL function. Running a compute shader doesn't actually do anything, but the Shader can modify data stored in `Texture`s or `ShaderBlock`s to get interesting things to happen.
+---
+---When running the compute shader, you can specify the number of times to run it in 3 dimensions, which is useful to iterate over large numbers of elements like pixels or array elements.
+---
+---@param shader lovr.Shader # The compute shader to run.
+---@param x? number # The amount of times to run in the x direction.
+---@param y? number # The amount of times to run in the y direction.
+---@param z? number # The amount of times to run in the z direction.
+function lovr.graphics.compute(shader, x, y, z) end
+
+---
+---Create the desktop window, usually used to mirror the headset display.
+---
+---@param flags {width: number, height: number, fullscreen: boolean, resizable: boolean, msaa: number, title: string, icon: string, vsync: number} # Flags to customize the window's appearance and behavior.
+function lovr.graphics.createWindow(flags) end
+
+---
+---Draws a cube.
+---
+---@overload fun(material: lovr.Material, x: number, y: number, z: number, size: number, angle: number, ax: number, ay: number, az: number)
+---@overload fun(mode: lovr.DrawStyle, transform: lovr.mat4)
+---@overload fun(material: lovr.Material, transform: lovr.mat4)
+---@param mode lovr.DrawStyle # How to draw the cube.
+---@param x? number # The x coordinate of the center of the cube.
+---@param y? number # The y coordinate of the center of the cube.
+---@param z? number # The z coordinate of the center of the cube.
+---@param size? number # The size of the cube, in meters.
+---@param angle? number # The rotation of the cube around its rotation axis, in radians.
+---@param ax? number # The x coordinate of the cube's axis of rotation.
+---@param ay? number # The y coordinate of the cube's axis of rotation.
+---@param az? number # The z coordinate of the cube's axis of rotation.
+function lovr.graphics.cube(mode, x, y, z, size, angle, ax, ay, az) end
+
+---
+---Draws a cylinder.
+---
+---@overload fun(material: lovr.Material, x: number, y: number, z: number, length: number, angle: number, ax: number, ay: number, az: number, r1: number, r2: number, capped: boolean, segments: number)
+---@param x? number # The x coordinate of the center of the cylinder.
+---@param y? number # The y coordinate of the center of the cylinder.
+---@param z? number # The z coordinate of the center of the cylinder.
+---@param length? number # The length of the cylinder, in meters.
+---@param angle? number # The rotation of the cylinder around its rotation axis, in radians.
+---@param ax? number # The x coordinate of the cylinder's axis of rotation.
+---@param ay? number # The y coordinate of the cylinder's axis of rotation.
+---@param az? number # The z coordinate of the cylinder's axis of rotation.
+---@param r1? number # The radius of one end of the cylinder.
+---@param r2? number # The radius of the other end of the cylinder.
+---@param capped? boolean # Whether the top and bottom should be rendered.
+---@param segments? number # The number of radial segments to use for the cylinder. If nil, the segment count is automatically determined from the radii.
+function lovr.graphics.cylinder(x, y, z, length, angle, ax, ay, az, r1, r2, capped, segments) end
+
+---
+---Discards pixel information in the active Canvas or display. This is mostly used as an optimization hint for the GPU, and is usually most helpful on mobile devices.
+---
+---@param color? boolean # Whether or not to discard color information.
+---@param depth? boolean # Whether or not to discard depth information.
+---@param stencil? boolean # Whether or not to discard stencil information.
+function lovr.graphics.discard(color, depth, stencil) end
+
+---
+---Draws a fullscreen textured quad.
+---
+---@overload fun()
+---@param texture lovr.Texture # The texture to use.
+---@param u? number # The x component of the uv offset.
+---@param v? number # The y component of the uv offset.
+---@param w? number # The width of the Texture to render, in uv coordinates.
+---@param h? number # The height of the Texture to render, in uv coordinates.
+function lovr.graphics.fill(texture, u, v, w, h) end
+
+---
+---Flushes the internal queue of draw batches. Under normal circumstances this is done automatically when needed, but the ability to flush manually may be helpful if you're integrating a LÖVR project with some external rendering code.
+---
+function lovr.graphics.flush() end
+
+---
+---Returns whether or not alpha sampling is enabled. Alpha sampling is also known as alpha-to-coverage. When it is enabled, the alpha channel of a pixel is factored into how antialiasing is computed, so the edges of a transparent texture will be correctly antialiased.
+---
+---@return boolean enabled # Whether or not alpha sampling is enabled.
+function lovr.graphics.getAlphaSampling() end
+
+---
+---Returns the current background color. Color components are from 0.0 to 1.0.
+---
+---@return number r # The red component of the background color.
+---@return number g # The green component of the background color.
+---@return number b # The blue component of the background color.
+---@return number a # The alpha component of the background color.
+function lovr.graphics.getBackgroundColor() end
+
+---
+---Returns the current blend mode. The blend mode controls how each pixel's color is blended with the previous pixel's color when drawn.
+---
+---If blending is disabled, `nil` will be returned.
+---
+---@return lovr.BlendMode blend # The current blend mode.
+---@return lovr.BlendAlphaMode alphaBlend # The current alpha blend mode.
+function lovr.graphics.getBlendMode() end
+
+---
+---Returns the active Canvas. Usually when you render something it will render directly to the headset. If a Canvas object is active, things will be rendered to the textures attached to the Canvas instead.
+---
+---@return lovr.Canvas canvas # The active Canvas, or `nil` if no canvas is set.
+function lovr.graphics.getCanvas() end
+
+---
+---Returns the current global color factor. Color components are from 0.0 to 1.0. Every pixel drawn will be multiplied (i.e. tinted) by this color.
+---
+---@return number r # The red component of the color.
+---@return number g # The green component of the color.
+---@return number b # The blue component of the color.
+---@return number a # The alpha component of the color.
+function lovr.graphics.getColor() end
+
+---
+---Returns a boolean for each color channel (red, green, blue, alpha) indicating whether it is enabled. When a color channel is enabled, it will be affected by drawing commands and clear commands.
+---
+function lovr.graphics.getColorMask() end
+
+---
+---Returns the default filter mode for new Textures. This controls how textures are sampled when they are minified, magnified, or stretched.
+---
+---@return lovr.FilterMode mode # The filter mode.
+---@return number anisotropy # The level of anisotropy.
+function lovr.graphics.getDefaultFilter() end
+
+---
+---Returns the current depth test settings.
+---
+---@return lovr.CompareMode compareMode # The current comparison method for depth testing.
+---@return boolean write # Whether pixels will have their z value updated when rendered to.
+function lovr.graphics.getDepthTest() end
+
+---
+---Returns the dimensions of the desktop window.
+---
+---@return number width # The width of the window, in pixels.
+---@return number height # The height of the window, in pixels.
+function lovr.graphics.getDimensions() end
+
+---
+---Returns whether certain features are supported by the system\'s graphics card.
+---
+---@return {astc: boolean, compute: boolean, dxt: boolean, instancedstereo: boolean, multiview: boolean, timers: boolean} features # A table of features and whether or not they are supported.
+function lovr.graphics.getFeatures() end
+
+---
+---Returns the active font.
+---
+---@return lovr.Font font # The active font object.
+function lovr.graphics.getFont() end
+
+---
+---Returns the height of the desktop window.
+---
+---@return number height # The height of the window, in pixels.
+function lovr.graphics.getHeight() end
+
+---
+---Returns information about the maximum limits of the graphics card, such as the maximum texture size or the amount of supported antialiasing.
+---
+---@return {anisotropy: number, blocksize: number, pointsize: number, texturemsaa: number, texturesize: number, compute: table} limits # The table of limits.
+function lovr.graphics.getLimits() end
+
+---
+---Returns the current line width.
+---
+---@return number width # The current line width, in pixels.
+function lovr.graphics.getLineWidth() end
+
+---
+---Returns the pixel density of the window. On "high-dpi" displays, this will be `2.0`, indicating that there are 2 pixels for every window coordinate. On a normal display it will be `1.0`, meaning that the pixel to window-coordinate ratio is 1:1.
+---
+---@return number density # The pixel density of the window.
+function lovr.graphics.getPixelDensity() end
+
+---
+---Returns the current point size.
+---
+---@return number size # The current point size, in pixels.
+function lovr.graphics.getPointSize() end
+
+---
+---Returns the projection for a single view.
+---
+---@overload fun(view: number, matrix: lovr.Mat4):lovr.Mat4
+---@param view number # The view index.
+---@return number left # The left field of view angle, in radians.
+---@return number right # The right field of view angle, in radians.
+---@return number up # The top field of view angle, in radians.
+---@return number down # The bottom field of view angle, in radians.
+function lovr.graphics.getProjection(view) end
+
+---
+---Returns the active shader.
+---
+---@return lovr.Shader shader # The active shader object, or `nil` if none is active.
+function lovr.graphics.getShader() end
+
+---
+---Returns graphics-related performance statistics for the current frame.
+---
+---@return {drawcalls: number, renderpasses: number, shaderswitches: number, buffers: number, textures: number, buffermemory: number, texturememory: number} stats # The table of stats.
+function lovr.graphics.getStats() end
+
+---
+---Returns the current stencil test. The stencil test lets you mask out pixels that meet certain criteria, based on the contents of the stencil buffer. The stencil buffer can be modified using `lovr.graphics.stencil`. After rendering to the stencil buffer, the stencil test can be set to control how subsequent drawing functions are masked by the stencil buffer.
+---
+---@return lovr.CompareMode compareMode # The comparison method used to decide if a pixel should be visible, or nil if the stencil test is disabled.
+---@return number compareValue # The value stencil values are compared against, or nil if the stencil test is disabled.
+function lovr.graphics.getStencilTest() end
+
+---
+---Get the pose of a single view.
+---
+---@overload fun(view: number, matrix: lovr.Mat4, invert: boolean):lovr.Mat4
+---@param view number # The view index.
+---@return number x # The x position of the viewer, in meters.
+---@return number y # The y position of the viewer, in meters.
+---@return number z # The z position of the viewer, in meters.
+---@return number angle # The number of radians the viewer is rotated around its axis of rotation.
+---@return number ax # The x component of the axis of rotation.
+---@return number ay # The y component of the axis of rotation.
+---@return number az # The z component of the axis of rotation.
+function lovr.graphics.getViewPose(view) end
+
+---
+---Returns the width of the desktop window.
+---
+---@return number width # The width of the window, in pixels.
+function lovr.graphics.getWidth() end
+
+---
+---Returns the current polygon winding. The winding direction determines which face of a triangle is the front face and which is the back face. This lets the graphics engine cull the back faces of polygons, improving performance.
+---
+---@return lovr.Winding winding # The current winding direction.
+function lovr.graphics.getWinding() end
+
+---
+---Returns whether the desktop window is currently created.
+---
+---@return boolean present # Whether a window is created.
+function lovr.graphics.hasWindow() end
+
+---
+---Returns whether or not culling is active. Culling is an optimization that avoids rendering the back face of polygons. This improves performance by reducing the number of polygons drawn, but requires that the vertices in triangles are specified in a consistent clockwise or counter clockwise order.
+---
+---@return boolean isEnabled # Whether or not culling is enabled.
+function lovr.graphics.isCullingEnabled() end
+
+---
+---Returns a boolean indicating whether or not wireframe rendering is enabled.
+---
+---@return boolean isWireframe # Whether or not wireframe rendering is enabled.
+function lovr.graphics.isWireframe() end
+
+---
+---Draws lines between points. Each point will be connected to the previous point in the list.
+---
+---@overload fun(points: table)
+---@param x1 number # The x coordinate of the first point.
+---@param y1 number # The y coordinate of the first point.
+---@param z1 number # The z coordinate of the first point.
+---@param x2 number # The x coordinate of the second point.
+---@param y2 number # The y coordinate of the second point.
+---@param z2 number # The z coordinate of the second point.
+function lovr.graphics.line(x1, y1, z1, x2, y2, z2) end
+
+---
+---Creates a new Canvas. You can specify Textures to attach to it, or just specify a width and height and attach textures later using `Canvas:setTexture`.
+---
+---Once created, you can render to the Canvas using `Canvas:renderTo`, or `lovr.graphics.setCanvas`.
+---
+---@overload fun(..., flags: table):lovr.Canvas
+---@overload fun(attachments: table, flags: table):lovr.Canvas
+---@param width number # The width of the canvas, in pixels.
+---@param height number # The height of the canvas, in pixels.
+---@param flags? {format: lovr.TextureFormat, depth: lovr.TextureFormat, stereo: boolean, msaa: number, mipmaps: boolean} # Optional settings for the Canvas.
+---@return lovr.Canvas canvas # The new Canvas.
+function lovr.graphics.newCanvas(width, height, flags) end
+
+---
+---Creates a new compute Shader, used for running generic compute operations on the GPU.
+---
+---@param source string # The code or filename of the compute shader.
+---@param options? {flags: table} # Optional settings for the Shader.
+---@return lovr.Shader shader # The new compute Shader.
+function lovr.graphics.newComputeShader(source, options) end
+
+---
+---Creates a new Font. It can be used to render text with `lovr.graphics.print`.
+---
+---Currently, the only supported font format is TTF.
+---
+---@overload fun(size: number, padding: number, spread: number):lovr.Font
+---@overload fun(rasterizer: lovr.Rasterizer, padding: number, spread: number):lovr.Font
+---@param filename string # The filename of the font file.
+---@param size? number # The size of the font, in pixels.
+---@param padding? number # The number of pixels of padding around each glyph.
+---@param spread? number # The range of the distance field, in pixels.
+---@return lovr.Font font # The new Font.
+function lovr.graphics.newFont(filename, size, padding, spread) end
+
+---
+---Creates a new Material. Materials are sets of colors, textures, and other parameters that affect the appearance of objects. They can be applied to `Model`s, `Mesh`es, and most graphics primitives accept a Material as an optional first argument.
+---
+---@overload fun(texture: lovr.Texture, r: number, g: number, b: number, a: number):lovr.Material
+---@overload fun(canvas: lovr.Canvas, r: number, g: number, b: number, a: number):lovr.Material
+---@overload fun(r: number, g: number, b: number, a: number):lovr.Material
+---@overload fun(hex: number, a: number):lovr.Material
+---@return lovr.Material material # The new Material.
+function lovr.graphics.newMaterial() end
+
+---
+---Creates a new Mesh. Meshes contain the data for an arbitrary set of vertices, and can be drawn. You must specify either the capacity for the Mesh or an initial set of vertex data. Optionally, a custom format table can be used to specify the set of vertex attributes the mesh will provide to the active shader. The draw mode and usage hint can also optionally be specified.
+---
+---The default data type for an attribute is `float`, and the default component count is 1.
+---
+---@overload fun(vertices: table, mode: lovr.DrawMode, usage: lovr.MeshUsage, readable: boolean):lovr.Mesh
+---@overload fun(blob: lovr.Blob, mode: lovr.DrawMode, usage: lovr.MeshUsage, readable: boolean):lovr.Mesh
+---@overload fun(format: table, size: number, mode: lovr.DrawMode, usage: lovr.MeshUsage, readable: boolean):lovr.Mesh
+---@overload fun(format: table, vertices: table, mode: lovr.DrawMode, usage: lovr.MeshUsage, readable: boolean):lovr.Mesh
+---@overload fun(format: table, blob: lovr.Blob, mode: lovr.DrawMode, usage: lovr.MeshUsage, readable: boolean):lovr.Mesh
+---@param size number # The maximum number of vertices the Mesh can store.
+---@param mode? lovr.DrawMode # How the Mesh will connect its vertices into triangles.
+---@param usage? lovr.MeshUsage # An optimization hint indicating how often the data in the Mesh will be updated.
+---@param readable? boolean # Whether vertices from the Mesh can be read.
+---@return lovr.Mesh mesh # The new Mesh.
+function lovr.graphics.newMesh(size, mode, usage, readable) end
+
+---
+---Creates a new Model from a file. The supported 3D file formats are OBJ, glTF, and STL.
+---
+---@overload fun(modelData: lovr.ModelData):lovr.Model
+---@param filename string # The filename of the model to load.
+---@return lovr.Model model # The new Model.
+function lovr.graphics.newModel(filename) end
+
+---
+---Creates a new Shader.
+---
+---@overload fun(default: lovr.DefaultShader, options: table):lovr.Shader
+---@param vertex string # The code or filename of the vertex shader. If nil, the default vertex shader is used.
+---@param fragment string # The code or filename of the fragment shader. If nil, the default fragment shader is used.
+---@param options? {flags: table, stereo: boolean} # Optional settings for the Shader.
+---@return lovr.Shader shader # The new Shader.
+function lovr.graphics.newShader(vertex, fragment, options) end
+
+---
+---Creates a new ShaderBlock from a table of variable definitions with their names and types.
+---
+---@param type lovr.BlockType # Whether the block will be used for read-only uniform data or compute shaders.
+---@param uniforms table # A table where the keys are uniform names and the values are uniform types. Uniform arrays can be specified by supplying a table as the uniform's value containing the type and the array size.
+---@param flags? {usage: lovr.BufferUsage, readable: boolean} # Optional settings.
+---@return lovr.ShaderBlock shaderBlock # The new ShaderBlock.
+function lovr.graphics.newShaderBlock(type, uniforms, flags) end
+
+---
+---Creates a new Texture from an image file.
+---
+---@overload fun(images: table, flags: table):lovr.Texture
+---@overload fun(width: number, height: number, depth: number, flags: table):lovr.Texture
+---@overload fun(blob: lovr.Blob, flags: table):lovr.Texture
+---@overload fun(image: lovr.Image, flags: table):lovr.Texture
+---@param filename string # The filename of the image to load.
+---@param flags? {linear: boolean, mipmaps: boolean, type: lovr.TextureType, format: lovr.TextureFormat, msaa: number} # Optional settings for the texture.
+---@return lovr.Texture texture # The new Texture.
+function lovr.graphics.newTexture(filename, flags) end
+
+---
+---Resets the transformation to the origin.
+---
+function lovr.graphics.origin() end
+
+---
+---Draws a plane with a given position, size, and orientation.
+---
+---@overload fun(material: lovr.Material, x: number, y: number, z: number, width: number, height: number, angle: number, ax: number, ay: number, az: number, u: number, v: number, w: number, h: number)
+---@param mode lovr.DrawStyle # How to draw the plane.
+---@param x? number # The x coordinate of the center of the plane.
+---@param y? number # The y coordinate of the center of the plane.
+---@param z? number # The z coordinate of the center of the plane.
+---@param width? number # The width of the plane, in meters.
+---@param height? number # The height of the plane, in meters.
+---@param angle? number # The number of radians to rotate around the rotation axis.
+---@param ax? number # The x component of the rotation axis.
+---@param ay? number # The y component of the rotation axis.
+---@param az? number # The z component of the rotation axis.
+---@param u? number # The u coordinate of the texture.
+---@param v? number # The v coordinate of the texture.
+---@param w? number # The width of the texture UVs to render.
+---@param h? number # The height of the texture UVs to render.
+function lovr.graphics.plane(mode, x, y, z, width, height, angle, ax, ay, az, u, v, w, h) end
+
+---
+---Draws one or more points.
+---
+---@overload fun(points: table)
+---@param x number # The x coordinate of the point.
+---@param y number # The y coordinate of the point.
+---@param z number # The z coordinate of the point.
+function lovr.graphics.points(x, y, z) end
+
+---
+---Pops the current transform from the stack, returning to the transformation that was applied before `lovr.graphics.push` was called.
+---
+function lovr.graphics.pop() end
+
+---
+---Presents the results of pending drawing operations to the window. This is automatically called after `lovr.draw` by the default `lovr.run` function.
+---
+function lovr.graphics.present() end
+
+---
+---Draws text in 3D space using the active font.
+---
+---@param str string # The text to render.
+---@param x? number # The x coordinate of the center of the text.
+---@param y? number # The y coordinate of the center of the text.
+---@param z? number # The z coordinate of the center of the text.
+---@param scale? number # The scale of the text.
+---@param angle? number # The number of radians to rotate the text around its rotation axis.
+---@param ax? number # The x component of the axis of rotation.
+---@param ay? number # The y component of the axis of rotation.
+---@param az? number # The z component of the axis of rotation.
+---@param wrap? number # The maximum width of each line, in meters (before scale is applied). Set to 0 or nil for no wrapping.
+---@param halign? lovr.HorizontalAlign # The horizontal alignment.
+---@param valign? lovr.VerticalAlign # The vertical alignment.
+function lovr.graphics.print(str, x, y, z, scale, angle, ax, ay, az, wrap, halign, valign) end
+
+---
+---Pushes a copy of the current transform onto the transformation stack. After changing the transform using `lovr.graphics.translate`, `lovr.graphics.rotate`, and `lovr.graphics.scale`, the original state can be restored using `lovr.graphics.pop`.
+---
+function lovr.graphics.push() end
+
+---
+---Resets all graphics state to the initial values.
+---
+function lovr.graphics.reset() end
+
+---
+---Rotates the coordinate system around an axis.
+---
+---The rotation will last until `lovr.draw` returns or the transformation is popped off the transformation stack.
+---
+---@param angle? number # The amount to rotate the coordinate system by, in radians.
+---@param ax? number # The x component of the axis of rotation.
+---@param ay? number # The y component of the axis of rotation.
+---@param az? number # The z component of the axis of rotation.
+function lovr.graphics.rotate(angle, ax, ay, az) end
+
+---
+---Scales the coordinate system in 3 dimensions. This will cause objects to appear bigger or smaller.
+---
+---The scaling will last until `lovr.draw` returns or the transformation is popped off the transformation stack.
+---
+---@param x? number # The amount to scale on the x axis.
+---@param y? number # The amount to scale on the y axis.
+---@param z? number # The amount to scale on the z axis.
+function lovr.graphics.scale(x, y, z) end
+
+---
+---Enables or disables alpha sampling. Alpha sampling is also known as alpha-to-coverage. When it is enabled, the alpha channel of a pixel is factored into how antialiasing is computed, so the edges of a transparent texture will be correctly antialiased.
+---
+---@param enabled boolean # Whether or not alpha sampling is enabled.
+function lovr.graphics.setAlphaSampling(enabled) end
+
+---
+---Sets the background color used to clear the screen. Color components are from 0.0 to 1.0.
+---
+---@overload fun(hex: number, a: number)
+---@overload fun(color: table)
+---@param r number # The red component of the background color.
+---@param g number # The green component of the background color.
+---@param b number # The blue component of the background color.
+---@param a? number # The alpha component of the background color.
+function lovr.graphics.setBackgroundColor(r, g, b, a) end
+
+---
+---Sets the blend mode. The blend mode controls how each pixel's color is blended with the previous pixel's color when drawn.
+---
+---@overload fun()
+---@param blend lovr.BlendMode # The blend mode.
+---@param alphaBlend lovr.BlendAlphaMode # The alpha blend mode.
+function lovr.graphics.setBlendMode(blend, alphaBlend) end
+
+---
+---Sets or disables the active Canvas object. If there is an active Canvas, things will be rendered to the Textures attached to that Canvas instead of to the headset.
+---
+---@param canvas? lovr.Canvas # The new active Canvas object, or `nil` to just render to the headset.
+function lovr.graphics.setCanvas(canvas) end
+
+---
+---Sets the color used for drawing objects. Color components are from 0.0 to 1.0. Every pixel drawn will be multiplied (i.e. tinted) by this color. This is a global setting, so it will affect all subsequent drawing operations.
+---
+---@overload fun(hex: number, a: number)
+---@overload fun(color: table)
+---@param r number # The red component of the color.
+---@param g number # The green component of the color.
+---@param b number # The blue component of the color.
+---@param a? number # The alpha component of the color.
+function lovr.graphics.setColor(r, g, b, a) end
+
+---
+---Enables and disables individual color channels. When a color channel is enabled, it will be affected by drawing commands and clear commands.
+---
+---@param r boolean # Whether the red color channel should be enabled.
+---@param g boolean # Whether the green color channel should be enabled.
+---@param b boolean # Whether the blue color channel should be enabled.
+---@param a boolean # Whether the alpha color channel should be enabled.
+function lovr.graphics.setColorMask(r, g, b, a) end
+
+---
+---Enables or disables culling. Culling is an optimization that avoids rendering the back face of polygons. This improves performance by reducing the number of polygons drawn, but requires that the vertices in triangles are specified in a consistent clockwise or counter clockwise order.
+---
+---@param isEnabled boolean # Whether or not culling should be enabled.
+function lovr.graphics.setCullingEnabled(isEnabled) end
+
+---
+---Sets the default filter mode for new Textures. This controls how textures are sampled when they are minified, magnified, or stretched.
+---
+---@param mode lovr.FilterMode # The filter mode.
+---@param anisotropy number # The level of anisotropy to use.
+function lovr.graphics.setDefaultFilter(mode, anisotropy) end
+
+---
+---Sets the current depth test. The depth test controls how overlapping objects are rendered.
+---
+---@param compareMode? lovr.CompareMode # The new depth test. Use `nil` to disable the depth test.
+---@param write? boolean # Whether pixels will have their z value updated when rendered to.
+function lovr.graphics.setDepthTest(compareMode, write) end
+
+---
+---Sets the active font used to render text with `lovr.graphics.print`.
+---
+---@param font? lovr.Font # The font to use. If `nil`, the default font is used (Varela Round).
+function lovr.graphics.setFont(font) end
+
+---
+---Sets the width of lines rendered using `lovr.graphics.line`.
+---
+---@param width? number # The new line width, in pixels.
+function lovr.graphics.setLineWidth(width) end
+
+---
+---Sets the width of drawn points, in pixels.
+---
+---@param size? number # The new point size.
+function lovr.graphics.setPointSize(size) end
+
+---
+---Sets the projection for a single view. 4 field of view angles can be used, similar to the field of view returned by `lovr.headset.getViewAngles`. Alternatively, a projection matrix can be used for other types of projections like orthographic, oblique, etc.
+---
+---Two views are supported, one for each eye. When rendering to the headset, both projections are changed to match the ones used by the headset.
+---
+---@overload fun(view: number, matrix: lovr.Mat4)
+---@param view number # The index of the view to update.
+---@param left number # The left field of view angle, in radians.
+---@param right number # The right field of view angle, in radians.
+---@param up number # The top field of view angle, in radians.
+---@param down number # The bottom field of view angle, in radians.
+function lovr.graphics.setProjection(view, left, right, up, down) end
+
+---
+---Sets or disables the Shader used for drawing.
+---
+---@overload fun()
+---@param shader lovr.Shader # The shader to use.
+function lovr.graphics.setShader(shader) end
+
+---
+---Sets the stencil test. The stencil test lets you mask out pixels that meet certain criteria, based on the contents of the stencil buffer. The stencil buffer can be modified using `lovr.graphics.stencil`. After rendering to the stencil buffer, the stencil test can be set to control how subsequent drawing functions are masked by the stencil buffer.
+---
+---@overload fun()
+---@param compareMode lovr.CompareMode # The comparison method used to decide if a pixel should be visible, or nil if the stencil test is disabled.
+---@param compareValue number # The value to compare stencil values to.
+function lovr.graphics.setStencilTest(compareMode, compareValue) end
+
+---
+---Sets the pose for a single view. Objects rendered in this view will appear as though the camera is positioned using the given pose.
+---
+---Two views are supported, one for each eye. When rendering to the headset, both views are changed to match the estimated eye positions. These view poses are also available using `lovr.headset.getViewPose`.
+---
+---@overload fun(view: number, matrix: lovr.Mat4, inverted: boolean)
+---@param view number # The index of the view to update.
+---@param x number # The x position of the viewer, in meters.
+---@param y number # The y position of the viewer, in meters.
+---@param z number # The z position of the viewer, in meters.
+---@param angle number # The number of radians the viewer is rotated around its axis of rotation.
+---@param ax number # The x component of the axis of rotation.
+---@param ay number # The y component of the axis of rotation.
+---@param az number # The z component of the axis of rotation.
+function lovr.graphics.setViewPose(view, x, y, z, angle, ax, ay, az) end
+
+---
+---Sets the polygon winding. The winding direction determines which face of a triangle is the front face and which is the back face. This lets the graphics engine cull the back faces of polygons, improving performance. The default is counterclockwise.
+---
+---@param winding lovr.Winding # The new winding direction.
+function lovr.graphics.setWinding(winding) end
+
+---
+---Enables or disables wireframe rendering. This is meant to be used as a debugging tool.
+---
+---@param wireframe boolean # Whether or not wireframe rendering should be enabled.
+function lovr.graphics.setWireframe(wireframe) end
+
+---
+---Render a skybox from a texture. Two common kinds of skybox textures are supported: A 2D equirectangular texture with a spherical coordinates can be used, or a "cubemap" texture created from 6 images.
+---
+---@param texture lovr.Texture # The texture to use.
+function lovr.graphics.skybox(texture) end
+
+---
+---Draws a sphere.
+---
+---@overload fun(material: lovr.Material, x: number, y: number, z: number, radius: number, angle: number, ax: number, ay: number, az: number)
+---@param x? number # The x coordinate of the center of the sphere.
+---@param y? number # The y coordinate of the center of the sphere.
+---@param z? number # The z coordinate of the center of the sphere.
+---@param radius? number # The radius of the sphere, in meters.
+---@param angle? number # The rotation of the sphere around its rotation axis, in radians.
+---@param ax? number # The x coordinate of the sphere's axis of rotation.
+---@param ay? number # The y coordinate of the sphere's axis of rotation.
+---@param az? number # The z coordinate of the sphere's axis of rotation.
+function lovr.graphics.sphere(x, y, z, radius, angle, ax, ay, az) end
+
+---
+---Renders to the stencil buffer using a function.
+---
+---@overload fun(callback: function, action: lovr.StencilAction, value: number, initial: number)
+---@param callback function # The function that will be called to render to the stencil buffer.
+---@param action? lovr.StencilAction # How to modify the stencil value of pixels that are rendered to.
+---@param value? number # If `action` is "replace", this is the value that pixels are replaced with.
+---@param keep? boolean # If false, the stencil buffer will be cleared to zero before rendering.
+function lovr.graphics.stencil(callback, action, value, keep) end
+
+---
+---Starts a named timer on the GPU, which can be stopped using `lovr.graphics.tock`.
+---
+---@param label string # The name of the timer.
+function lovr.graphics.tick(label) end
+
+---
+---Stops a named timer on the GPU, previously started with `lovr.graphics.tick`.
+---
+---@param label string # The name of the timer.
+---@return number time # The number of seconds elapsed, or `nil` if the data isn't ready yet.
+function lovr.graphics.tock(label) end
+
+---
+---Apply a transform to the coordinate system, changing its translation, rotation, and scale using a single function. A `mat4` can also be used.
+---
+---The transformation will last until `lovr.draw` returns or the transformation is popped off the transformation stack.
+---
+---@overload fun(transform: lovr.mat4)
+---@param x? number # The x component of the translation.
+---@param y? number # The y component of the translation.
+---@param z? number # The z component of the translation.
+---@param sx? number # The x scale factor.
+---@param sy? number # The y scale factor.
+---@param sz? number # The z scale factor.
+---@param angle? number # The number of radians to rotate around the rotation axis.
+---@param ax? number # The x component of the axis of rotation.
+---@param ay? number # The y component of the axis of rotation.
+---@param az? number # The z component of the axis of rotation.
+function lovr.graphics.transform(x, y, z, sx, sy, sz, angle, ax, ay, az) end
+
+---
+---Translates the coordinate system in three dimensions. All graphics operations that use coordinates will behave as if they are offset by the translation value.
+---
+---The translation will last until `lovr.draw` returns or the transformation is popped off the transformation stack.
+---
+---@param x? number # The amount to translate on the x axis.
+---@param y? number # The amount to translate on the y axis.
+---@param z? number # The amount to translate on the z axis.
+function lovr.graphics.translate(x, y, z) end
+
+---
+---Different ways arcs can be drawn with `lovr.graphics.arc`.
+---
+---@class lovr.ArcMode
+---
+---The arc is drawn with the center of its circle included in the list of points (default).
+---
+---@field pie integer
+---
+---The curve of the arc is drawn as a single line.
+---
+---@field open integer
+---
+---The starting and ending points of the arc's curve are connected.
+---
+---@field closed integer
+
+---
+---Here are the different data types available for vertex attributes in a Mesh. The ones that have a smaller range take up less memory, which improves performance a bit. The "u" stands for "unsigned", which means it can't hold negative values but instead has a larger positive range.
+---
+---@class lovr.AttributeType
+---
+---A signed 8 bit number, from -128 to 127.
+---
+---@field byte integer
+---
+---An unsigned 8 bit number, from 0 to 255.
+---
+---@field ubyte integer
+---
+---A signed 16 bit number, from -32768 to 32767.
+---
+---@field short integer
+---
+---An unsigned 16 bit number, from 0 to 65535.
+---
+---@field ushort integer
+---
+---A signed 32 bit number, from -2147483648 to 2147483647.
+---
+---@field int integer
+---
+---An unsigned 32 bit number, from 0 to 4294967295.
+---
+---@field uint integer
+---
+---A 32 bit floating-point number (large range, but can start to lose precision).
+---
+---@field float integer
+
+---
+---Different ways the alpha channel of pixels affects blending.
+---
+---@class lovr.BlendAlphaMode
+---
+---Color channel values are multiplied by the alpha channel during blending.
+---
+---@field alphamultiply integer
+---
+---Color channels are not multiplied by the alpha channel. This should be used if the pixels being drawn have already been blended, or "pre-multiplied", by the alpha channel.
+---
+---@field premultiplied integer
+
+---
+---Blend modes control how overlapping pixels are blended together, similar to layers in Photoshop.
+---
+---@class lovr.BlendMode
+---
+---Normal blending where the alpha value controls how the colors are blended.
+---
+---@field alpha integer
+---
+---The incoming pixel color is added to the destination pixel color.
+---
+---@field add integer
+---
+---The incoming pixel color is subtracted from the destination pixel color.
+---
+---@field subtract integer
+---
+---The color channels from the two pixel values are multiplied together to produce a result.
+---
+---@field multiply integer
+---
+---The maximum value from each color channel is used, resulting in a lightening effect.
+---
+---@field lighten integer
+---
+---The minimum value from each color channel is used, resulting in a darkening effect.
+---
+---@field darken integer
+---
+---The opposite of multiply: The pixel values are inverted, multiplied, and inverted again, resulting in a lightening effect.
+---
+---@field screen integer
+
+---
+---There are two types of ShaderBlocks that can be used: `uniform` and `compute`.
+---
+---Uniform blocks are read only in shaders, can sometimes be a bit faster than compute blocks, and have a limited size (but the limit will be at least 16KB, you can check `lovr.graphics.getLimits` to check).
+---
+---Compute blocks can be written to by compute shaders, might be slightly slower than uniform blocks, and have a much, much larger maximum size.
+---
+---@class lovr.BlockType
+---
+---A uniform block.
+---
+---@field uniform integer
+---
+---A compute block.
+---
+---@field compute integer
+
+---
+---This acts as a hint to the graphics driver about what kinds of data access should be optimized for.
+---
+---@class lovr.BufferUsage
+---
+---A buffer that you intend to create once and never modify.
+---
+---@field static integer
+---
+---A buffer which is modified occasionally.
+---
+---@field dynamic integer
+---
+---A buffer which is entirely replaced on the order of every frame.
+---
+---@field stream integer
+
+---
+---The method used to compare z values when deciding how to overlap rendered objects. This is called the "depth test", and it happens on a pixel-by-pixel basis every time new objects are drawn. If the depth test "passes" for a pixel, then the pixel color will be replaced by the new color and the depth value in the depth buffer will be updated. Otherwise, the pixel will not be changed and the depth value will not be updated.
+---
+---@class lovr.CompareMode
+---
+---The depth test passes when the depth values are equal.
+---
+---@field equal integer
+---
+---The depth test passes when the depth values are not equal.
+---
+---@field notequal integer
+---
+---The depth test passes when the new depth value is less than the existing one.
+---
+---@field less integer
+---
+---The depth test passes when the new depth value is less than or equal to the existing one.
+---
+---@field lequal integer
+---
+---The depth test passes when the new depth value is greater than or equal to the existing one.
+---
+---@field gequal integer
+---
+---The depth test passes when the new depth value is greater than the existing one.
+---
+---@field greater integer
+
+---
+---Different coordinate spaces for nodes in a Model.
+---
+---@class lovr.CoordinateSpace
+---
+---The coordinate space relative to the node's parent.
+---
+---@field local integer
+---
+---The coordinate space relative to the root node of the Model.
+---
+---@field global integer
+
+---
+---The following shaders are built in to LÖVR, and can be used as an argument to `lovr.graphics.newShader` instead of providing raw GLSL shader code. The shaders can be further customized by using the `flags` argument. If you pass in `nil` to `lovr.graphics.setShader`, LÖVR will automatically pick a DefaultShader to use based on whatever is being drawn.
+---
+---@class lovr.DefaultShader
+---
+---A simple shader without lighting, using only colors and a diffuse texture.
+---
+---@field unlit integer
+---
+---A physically-based rendering (PBR) shader, using advanced material properties.
+---
+---@field standard integer
+---
+---A shader that renders a cubemap texture.
+---
+---@field cube integer
+---
+---A shader that renders a 2D equirectangular texture with spherical coordinates.
+---
+---@field pano integer
+---
+---A shader that renders font glyphs.
+---
+---@field font integer
+---
+---A shader that passes its vertex coordinates unmodified to the fragment shader, used to render view-independent fixed geometry like fullscreen quads.
+---
+---@field fill integer
+
+---
+---Meshes are lists of arbitrary vertices. These vertices can be connected in different ways, leading to different shapes like lines and triangles.
+---
+---@class lovr.DrawMode
+---
+---Draw each vertex as a single point.
+---
+---@field points integer
+---
+---The vertices represent a list of line segments. Each pair of vertices will have a line drawn between them.
+---
+---@field lines integer
+---
+---The first two vertices have a line drawn between them, and each vertex after that will be connected to the previous vertex with a line.
+---
+---@field linestrip integer
+---
+---Similar to linestrip, except the last vertex is connected back to the first.
+---
+---@field lineloop integer
+---
+---The first three vertices define a triangle. Each vertex after that creates a triangle using the new vertex and last two vertices.
+---
+---@field strip integer
+---
+---Each set of three vertices represents a discrete triangle.
+---
+---@field triangles integer
+---
+---Draws a set of triangles. Each one shares the first vertex as a common point, leading to a fan-like shape.
+---
+---@field fan integer
+
+---
+---Most graphics primitives can be drawn in one of two modes: a filled mode and a wireframe mode.
+---
+---@class lovr.DrawStyle
+---
+---The shape is drawn as a filled object.
+---
+---@field fill integer
+---
+---The shape is drawn as a wireframe object.
+---
+---@field line integer
+
+---
+---The method used to downsample (or upsample) a texture. "nearest" can be used for a pixelated effect, whereas "linear" leads to more smooth results. Nearest is slightly faster than linear.
+---
+---@class lovr.FilterMode
+---
+---Fast nearest-neighbor sampling. Leads to a pixelated style.
+---
+---@field nearest integer
+---
+---Smooth pixel sampling.
+---
+---@field bilinear integer
+---
+---Smooth pixel sampling, with smooth sampling across mipmap levels.
+---
+---@field trilinear integer
+
+---
+---Different ways to horizontally align text when using `lovr.graphics.print`.
+---
+---@class lovr.HorizontalAlign
+---
+---Left aligned lines of text.
+---
+---@field left integer
+---
+---Centered aligned lines of text.
+---
+---@field center integer
+---
+---Right aligned lines of text.
+---
+---@field right integer
+
+---
+---The different types of color parameters `Material`s can hold.
+---
+---@class lovr.MaterialColor
+---
+---The diffuse color.
+---
+---@field diffuse integer
+---
+---The emissive color.
+---
+---@field emissive integer
+
+---
+---The different types of float parameters `Material`s can hold.
+---
+---@class lovr.MaterialScalar
+---
+---The constant metalness factor.
+---
+---@field metalness integer
+---
+---The constant roughness factor.
+---
+---@field roughness integer
+
+---
+---The different types of texture parameters `Material`s can hold.
+---
+---@class lovr.MaterialTexture
+---
+---The diffuse texture.
+---
+---@field diffuse integer
+---
+---The emissive texture.
+---
+---@field emissive integer
+---
+---The metalness texture.
+---
+---@field metalness integer
+---
+---The roughness texture.
+---
+---@field roughness integer
+---
+---The ambient occlusion texture.
+---
+---@field occlusion integer
+---
+---The normal map.
+---
+---@field normal integer
+---
+---The environment map, should be specified as a cubemap texture.
+---
+---@field environment integer
+
+---
+---Meshes can have a usage hint, describing how they are planning on being updated. Setting the usage hint allows the graphics driver optimize how it handles the data in the Mesh.
+---
+---@class lovr.MeshUsage
+---
+---The Mesh contents will rarely change.
+---
+---@field static integer
+---
+---The Mesh contents will change often.
+---
+---@field dynamic integer
+---
+---The Mesh contents will change constantly, potentially multiple times each frame.
+---
+---@field stream integer
+
+---
+---Shaders can be used for either rendering operations or generic compute tasks. Graphics shaders are created with `lovr.graphics.newShader` and compute shaders are created with `lovr.graphics.newComputeShader`. `Shader:getType` can be used on an existing Shader to figure out what type it is.
+---
+---@class lovr.ShaderType
+---
+---A graphics shader.
+---
+---@field graphics integer
+---
+---A compute shader.
+---
+---@field compute integer
+
+---
+---How to modify pixels in the stencil buffer when using `lovr.graphics.stencil`.
+---
+---@class lovr.StencilAction
+---
+---Stencil values will be replaced with a custom value.
+---
+---@field replace integer
+---
+---Stencil values will increment every time they are rendered to.
+---
+---@field increment integer
+---
+---Stencil values will decrement every time they are rendered to.
+---
+---@field decrement integer
+---
+---Similar to `increment`, but the stencil value will be set to 0 if it exceeds 255.
+---
+---@field incrementwrap integer
+---
+---Similar to `decrement`, but the stencil value will be set to 255 if it drops below 0.
+---
+---@field decrementwrap integer
+---
+---Stencil values will be bitwise inverted every time they are rendered to.
+---
+---@field invert integer
+
+---
+---Textures can store their pixels in different formats. The set of color channels and the number of bits stored for each channel can differ, allowing Textures to optimize their storage for certain kinds of image formats or rendering techniques.
+---
+---@class lovr.TextureFormat
+---
+---Each pixel is 24 bits, or 8 bits for each channel.
+---
+---@field rgb integer
+---
+---Each pixel is 32 bits, or 8 bits for each channel (including alpha).
+---
+---@field rgba integer
+---
+---An rgba format where the colors occupy 4 bits instead of the usual 8.
+---
+---@field rgba4 integer
+---
+---Each pixel is 64 bits. Each channel is a 16 bit floating point number.
+---
+---@field rgba16f integer
+---
+---Each pixel is 128 bits. Each channel is a 32 bit floating point number.
+---
+---@field rgba32f integer
+---
+---A 16-bit floating point format with a single color channel.
+---
+---@field r16f integer
+---
+---A 32-bit floating point format with a single color channel.
+---
+---@field r32f integer
+---
+---A 16-bit floating point format with two color channels.
+---
+---@field rg16f integer
+---
+---A 32-bit floating point format with two color channels.
+---
+---@field rg32f integer
+---
+---A 16 bit format with 5-bit color channels and a single alpha bit.
+---
+---@field rgb5a1 integer
+---
+---A 32 bit format with 10-bit color channels and two alpha bits.
+---
+---@field rgb10a2 integer
+---
+---Each pixel is 32 bits, and packs three color channels into 10 or 11 bits each.
+---
+---@field rg11b10f integer
+---
+---A 16 bit depth buffer.
+---
+---@field d16 integer
+---
+---A 32 bit floating point depth buffer.
+---
+---@field d32f integer
+---
+---A depth buffer with 24 bits for depth and 8 bits for stencil.
+---
+---@field d24s8 integer
+
+---
+---Different types of Textures.
+---
+---@class lovr.TextureType
+---
+---A 2D texture.
+---
+---@field ["2d"] integer
+---
+---A 2D array texture with multiple independent 2D layers.
+---
+---@field array integer
+---
+---A cubemap texture with 6 2D faces.
+---
+---@field cube integer
+---
+---A 3D volumetric texture consisting of multiple 2D layers.
+---
+---@field volume integer
+
+---
+---When binding writable resources to shaders using `Shader:sendBlock` and `Shader:sendImage`, an access pattern can be specified as a hint that says whether you plan to read or write to the resource (or both). Sometimes, LÖVR or the GPU driver can use this hint to get better performance or avoid stalling.
+---
+---@class lovr.UniformAccess
+---
+---The Shader will use the resource in a read-only fashion.
+---
+---@field read integer
+---
+---The Shader will use the resource in a write-only fashion.
+---
+---@field write integer
+---
+---The resource will be available for reading and writing.
+---
+---@field readwrite integer
+
+---
+---Different ways to vertically align text when using `lovr.graphics.print`.
+---
+---@class lovr.VerticalAlign
+---
+---Align the top of the text to the origin.
+---
+---@field top integer
+---
+---Vertically center the text.
+---
+---@field middle integer
+---
+---Align the bottom of the text to the origin.
+---
+---@field bottom integer
+
+---
+---Whether the points on triangles are specified in a clockwise or counterclockwise order.
+---
+---@class lovr.Winding
+---
+---Triangle vertices are specified in a clockwise order.
+---
+---@field clockwise integer
+---
+---Triangle vertices are specified in a counterclockwise order.
+---
+---@field counterclockwise integer
+
+---
+---The method used to render textures when texture coordinates are outside of the 0-1 range.
+---
+---@class lovr.WrapMode
+---
+---The texture will be clamped at its edges.
+---
+---@field clamp integer
+---
+---The texture repeats.
+---
+---@field repeat integer
+---
+---The texture will repeat, mirroring its appearance each time it repeats.
+---
+---@field mirroredrepeat integer
diff --git a/meta/3rd/lovr/library/lovr.headset.lua b/meta/3rd/lovr/library/lovr.headset.lua
new file mode 100644
index 00000000..c33226fc
--- /dev/null
+++ b/meta/3rd/lovr/library/lovr.headset.lua
@@ -0,0 +1,511 @@
+---@meta
+
+---
+---The `lovr.headset` module is where all the magical VR functionality is. With it, you can access connected VR hardware and get information about the available space the player has. Note that all units are reported in meters. Position `(0, 0, 0)` is the center of the play area.
+---
+---@class lovr.headset
+lovr.headset = {}
+
+---
+---Animates a device model to match its current input state. The buttons and joysticks on a controller will move as they're pressed/moved and hand models will move to match skeletal input.
+---
+---The model should have been created using `lovr.headset.newModel` with the `animated` flag set to `true`.
+---
+---@param device? lovr.Device # The device to use for the animation data.
+---@param model lovr.Model # The model to animate.
+---@return boolean success # Whether the animation was applied successfully to the Model. If the Model was not compatible or animation data for the device was not available, this will be `false`.
+function lovr.headset.animate(device, model) end
+
+---
+---Returns the current angular velocity of a device.
+---
+---@param device? lovr.Device # The device to get the velocity of.
+---@return number x # The x component of the angular velocity.
+---@return number y # The y component of the angular velocity.
+---@return number z # The z component of the angular velocity.
+function lovr.headset.getAngularVelocity(device) end
+
+---
+---Get the current state of an analog axis on a device. Some axes are multidimensional, for example a 2D touchpad or thumbstick with x/y axes. For multidimensional axes, this function will return multiple values, one number for each axis. In these cases, it can be useful to use the `select` function built in to Lua to select a particular axis component.
+---
+---@param device lovr.Device # The device.
+---@param axis lovr.DeviceAxis # The axis.
+function lovr.headset.getAxis(device, axis) end
+
+---
+---Returns the depth of the play area, in meters.
+---
+---@return number depth # The depth of the play area, in meters.
+function lovr.headset.getBoundsDepth() end
+
+---
+---Returns the size of the play area, in meters.
+---
+---@return number width # The width of the play area, in meters.
+---@return number depth # The depth of the play area, in meters.
+function lovr.headset.getBoundsDimensions() end
+
+---
+---Returns a list of points representing the boundaries of the play area, or `nil` if the current headset driver does not expose this information.
+---
+---@param t? table # A table to fill with the points. If `nil`, a new table will be created.
+---@return table points # A flat table of 3D points representing the play area boundaries.
+function lovr.headset.getBoundsGeometry(t) end
+
+---
+---Returns the width of the play area, in meters.
+---
+---@return number width # The width of the play area, in meters.
+function lovr.headset.getBoundsWidth() end
+
+---
+---Returns the near and far clipping planes used to render to the headset. Objects closer than the near clipping plane or further than the far clipping plane will be clipped out of view.
+---
+---@return number near # The distance to the near clipping plane, in meters.
+---@return number far # The distance to the far clipping plane, in meters.
+function lovr.headset.getClipDistance() end
+
+---
+---Returns the texture dimensions of the headset display (for one eye), in pixels.
+---
+---@return number width # The width of the display.
+---@return number height # The height of the display.
+function lovr.headset.getDisplayDimensions() end
+
+---
+---Returns the refresh rate of the headset display, in Hz.
+---
+---@return number frequency # The frequency of the display, or `nil` if I have no idea what it is.
+function lovr.headset.getDisplayFrequency() end
+
+---
+---Returns the height of the headset display (for one eye), in pixels.
+---
+---@return number height # The height of the display.
+function lovr.headset.getDisplayHeight() end
+
+---
+---Returns 2D triangle vertices that represent areas of the headset display that will never be seen by the user (due to the circular lenses). This area can be masked out by rendering it to the depth buffer or stencil buffer. Then, further drawing operations can skip rendering those pixels using the depth test (`lovr.graphics.setDepthTest`) or stencil test (`lovr.graphics.setStencilTest`), which improves performance.
+---
+---@return table points # A table of points. Each point is a table with two numbers between 0 and 1.
+function lovr.headset.getDisplayMask() end
+
+---
+---Returns the width of the headset display (for one eye), in pixels.
+---
+---@return number width # The width of the display.
+function lovr.headset.getDisplayWidth() end
+
+---
+---Returns the `HeadsetDriver` that is currently in use, optionally for a specific device. The order of headset drivers can be changed using `lovr.conf` to prefer or exclude specific VR APIs.
+---
+---@overload fun(device: lovr.Device):lovr.HeadsetDriver
+---@return lovr.HeadsetDriver driver # The driver of the headset in use, e.g. "OpenVR".
+function lovr.headset.getDriver() end
+
+---
+---Returns a table with all of the currently tracked hand devices.
+---
+---@return table hands # The currently tracked hand devices.
+function lovr.headset.getHands() end
+
+---
+---Returns a Texture that contains whatever is currently rendered to the headset.
+---
+---Sometimes this can be `nil` if the current headset driver doesn't have a mirror texture, which can happen if the driver renders directly to the display. Currently the `desktop`, `webxr`, and `vrapi` drivers do not have a mirror texture.
+---
+---It also isn't guaranteed that the same Texture will be returned by subsequent calls to this function. Currently, the `oculus` driver exhibits this behavior.
+---
+---@return lovr.Texture mirror # The mirror texture.
+function lovr.headset.getMirrorTexture() end
+
+---
+---Returns the name of the headset as a string. The exact string that is returned depends on the hardware and VR SDK that is currently in use.
+---
+---@return string name # The name of the headset as a string.
+function lovr.headset.getName() end
+
+---
+---Returns the current orientation of a device, in angle/axis form.
+---
+---@param device? lovr.Device # The device to get the orientation of.
+---@return number angle # The amount of rotation around the axis of rotation, in radians.
+---@return number ax # The x component of the axis of rotation.
+---@return number ay # The y component of the axis of rotation.
+---@return number az # The z component of the axis of rotation.
+function lovr.headset.getOrientation(device) end
+
+---
+---Returns the type of origin used for the tracking volume. The different types of origins are explained on the `HeadsetOrigin` page.
+---
+---@return lovr.HeadsetOrigin origin # The type of origin.
+function lovr.headset.getOriginType() end
+
+---
+---Returns the current position and orientation of a device.
+---
+---@param device? lovr.Device # The device to get the pose of.
+---@return number x # The x position.
+---@return number y # The y position.
+---@return number z # The z position.
+---@return number angle # The amount of rotation around the axis of rotation, in radians.
+---@return number ax # The x component of the axis of rotation.
+---@return number ay # The y component of the axis of rotation.
+---@return number az # The z component of the axis of rotation.
+function lovr.headset.getPose(device) end
+
+---
+---Returns the current position of a device, in meters, relative to the play area.
+---
+---@param device? lovr.Device # The device to get the position of.
+---@return number x # The x position of the device.
+---@return number y # The y position of the device.
+---@return number z # The z position of the device.
+function lovr.headset.getPosition(device) end
+
+---
+---Returns a list of joint poses tracked by a device. Currently, only hand devices are able to track joints.
+---
+---@overload fun(device: lovr.Device, t: table):table
+---@param device lovr.Device # The Device to query.
+---@return table poses # A list of joint poses for the device. Each pose is a table with 3 numbers for the position of the joint followed by 4 numbers for the angle/axis orientation of the joint.
+function lovr.headset.getSkeleton(device) end
+
+---
+---Returns the estimated time in the future at which the light from the pixels of the current frame will hit the eyes of the user.
+---
+---This can be used as a replacement for `lovr.timer.getTime` for timestamps that are used for rendering to get a smoother result that is synchronized with the display of the headset.
+---
+---@return number time # The predicted display time, in seconds.
+function lovr.headset.getTime() end
+
+---
+---Returns the current linear velocity of a device, in meters per second.
+---
+---@param device? lovr.Device # The device to get the velocity of.
+---@return number vx # The x component of the linear velocity.
+---@return number vy # The y component of the linear velocity.
+---@return number vz # The z component of the linear velocity.
+function lovr.headset.getVelocity(device) end
+
+---
+---Returns the view angles of one of the headset views.
+---
+---These can be used with `Mat4:fov` to create a projection matrix.
+---
+---If tracking data is unavailable for the view or the index is invalid, `nil` is returned.
+---
+---@param view number # The view index.
+---@return number left # The left view angle, in radians.
+---@return number right # The right view angle, in radians.
+---@return number top # The top view angle, in radians.
+---@return number bottom # The bottom view angle, in radians.
+function lovr.headset.getViewAngles(view) end
+
+---
+---Returns the number of views used for rendering. Each view consists of a pose in space and a set of angle values that determine the field of view.
+---
+---This is usually 2 for stereo rendering configurations, but it can also be different. For example, one way of doing foveated rendering uses 2 views for each eye -- one low quality view with a wider field of view, and a high quality view with a narrower field of view.
+---
+---@return number count # The number of views.
+function lovr.headset.getViewCount() end
+
+---
+---Returns the pose of one of the headset views. This info can be used to create view matrices or do other eye-dependent calculations.
+---
+---If tracking data is unavailable for the view or the index is invalid, `nil` is returned.
+---
+---@param view number # The view index.
+---@return number x # The x coordinate of the view position, in meters.
+---@return number y # The y coordinate of the view position, in meters.
+---@return number z # The z coordinate of the view position, in meters.
+---@return number angle # The amount of rotation around the rotation axis, in radians.
+---@return number ax # The x component of the axis of rotation.
+---@return number ay # The y component of the axis of rotation.
+---@return number az # The z component of the axis of rotation.
+function lovr.headset.getViewPose(view) end
+
+---
+---Returns whether a button on a device is pressed.
+---
+---@param device lovr.Device # The device.
+---@param button lovr.DeviceButton # The button.
+---@return boolean down # Whether the button on the device is currently pressed, or `nil` if the device does not have the specified button.
+function lovr.headset.isDown(device, button) end
+
+---
+---Returns whether a button on a device is currently touched.
+---
+---@param device lovr.Device # The device.
+---@param button lovr.DeviceButton # The button.
+---@return boolean touched # Whether the button on the device is currently touched, or `nil` if the device does not have the button or it isn't touch-sensitive.
+function lovr.headset.isTouched(device, button) end
+
+---
+---Returns whether any active headset driver is currently returning pose information for a device.
+---
+---@param device? lovr.Device # The device to get the pose of.
+---@return boolean tracked # Whether the device is currently tracked.
+function lovr.headset.isTracked(device) end
+
+---
+---Returns a new Model for the specified device.
+---
+---@param device? lovr.Device # The device to load a model for.
+---@param options? {animated: boolean} # Options for loading the model.
+---@return lovr.Model model # The new Model, or `nil` if a model could not be loaded.
+function lovr.headset.newModel(device, options) end
+
+---
+---Renders to each eye of the headset using a function.
+---
+---This function takes care of setting the appropriate graphics transformations to ensure that the scene is rendered as though it is being viewed through each eye of the player. It also takes care of setting the correct projection for the headset lenses.
+---
+---If the headset module is enabled, this function is called automatically by `lovr.run` with `lovr.draw` as the callback.
+---
+---@param callback function # The function used to render. Any functions called will render to the headset instead of to the window.
+function lovr.headset.renderTo(callback) end
+
+---
+---Sets the near and far clipping planes used to render to the headset. Objects closer than the near clipping plane or further than the far clipping plane will be clipped out of view.
+---
+---@param near number # The distance to the near clipping plane, in meters.
+---@param far number # The distance to the far clipping plane, in meters.
+function lovr.headset.setClipDistance(near, far) end
+
+---
+---Causes the device to vibrate with a custom strength, duration, and frequency, if possible.
+---
+---@param device? lovr.Device # The device to vibrate.
+---@param strength? number # The strength of the vibration (amplitude), between 0 and 1.
+---@param duration? number # The duration of the vibration, in seconds.
+---@param frequency? number # The frequency of the vibration, in hertz. 0 will use a default frequency.
+---@return boolean vibrated # Whether the vibration was successfully triggered by an active headset driver.
+function lovr.headset.vibrate(device, strength, duration, frequency) end
+
+---
+---Returns whether a button on a device was pressed this frame.
+---
+---@param device lovr.Device # The device.
+---@param button lovr.DeviceButton # The button to check.
+---@return boolean pressed # Whether the button on the device was pressed this frame.
+function lovr.headset.wasPressed(device, button) end
+
+---
+---Returns whether a button on a device was released this frame.
+---
+---@param device lovr.Device # The device.
+---@param button lovr.DeviceButton # The button to check.
+---@return boolean released # Whether the button on the device was released this frame.
+function lovr.headset.wasReleased(device, button) end
+
+---
+---Different types of input devices supported by the `lovr.headset` module.
+---
+---@class lovr.Device
+---
+---The headset.
+---
+---@field head integer
+---
+---The left controller.
+---
+---@field ["hand/left"] integer
+---
+---The right controller.
+---
+---@field ["hand/right"] integer
+---
+---A shorthand for hand/left.
+---
+---@field left integer
+---
+---A shorthand for hand/right.
+---
+---@field right integer
+---
+---A device tracking the left elbow.
+---
+---@field ["elbow/left"] integer
+---
+---A device tracking the right elbow.
+---
+---@field ["elbow/right"] integer
+---
+---A device tracking the left shoulder.
+---
+---@field ["shoulder/left"] integer
+---
+---A device tracking the right shoulder.
+---
+---@field ["shoulder/right"] integer
+---
+---A device tracking the chest.
+---
+---@field chest integer
+---
+---A device tracking the waist.
+---
+---@field waist integer
+---
+---A device tracking the left knee.
+---
+---@field ["knee/left"] integer
+---
+---A device tracking the right knee.
+---
+---@field ["knee/right"] integer
+---
+---A device tracking the left foot or ankle.
+---
+---@field ["foot/left"] integer
+---
+---A device tracking the right foot or ankle.
+---
+---@field ["foot/right"] integer
+---
+---A device used as a camera in the scene.
+---
+---@field camera integer
+---
+---A tracked keyboard.
+---
+---@field keyboard integer
+---
+---The left eye.
+---
+---@field ["eye/left"] integer
+---
+---The right eye.
+---
+---@field ["eye/right"] integer
+---
+---The first tracking device (i.e. lighthouse).
+---
+---@field ["beacon/1"] integer
+---
+---The second tracking device (i.e. lighthouse).
+---
+---@field ["beacon/2"] integer
+---
+---The third tracking device (i.e. lighthouse).
+---
+---@field ["beacon/3"] integer
+---
+---The fourth tracking device (i.e. lighthouse).
+---
+---@field ["beacon/4"] integer
+
+---
+---Axes on an input device.
+---
+---@class lovr.DeviceAxis
+---
+---A trigger (1D).
+---
+---@field trigger integer
+---
+---A thumbstick (2D).
+---
+---@field thumbstick integer
+---
+---A touchpad (2D).
+---
+---@field touchpad integer
+---
+---A grip button or grab gesture (1D).
+---
+---@field grip integer
+
+---
+---Buttons on an input device.
+---
+---@class lovr.DeviceButton
+---
+---The trigger button.
+---
+---@field trigger integer
+---
+---The thumbstick.
+---
+---@field thumbstick integer
+---
+---The touchpad.
+---
+---@field touchpad integer
+---
+---The grip button.
+---
+---@field grip integer
+---
+---The menu button.
+---
+---@field menu integer
+---
+---The A button.
+---
+---@field a integer
+---
+---The B button.
+---
+---@field b integer
+---
+---The X button.
+---
+---@field x integer
+---
+---The Y button.
+---
+---@field y integer
+---
+---The proximity sensor on a headset.
+---
+---@field proximity integer
+
+---
+---These are all of the supported VR APIs that LÖVR can use to power the lovr.headset module. You can change the order of headset drivers using `lovr.conf` to prefer or exclude specific VR APIs.
+---
+---At startup, LÖVR searches through the list of drivers in order. One headset driver will be used for rendering to the VR display, and all supported headset drivers will be used for device input. The way this works is that when poses or button input is requested, the input drivers are queried (in the order they appear in `conf.lua`) to see if any of them currently have data for the specified device. The first one that returns data will be used to provide the result. This allows projects to support multiple types of hardware devices.
+---
+---@class lovr.HeadsetDriver
+---
+---A VR simulator using keyboard/mouse.
+---
+---@field desktop integer
+---
+---Oculus Desktop SDK.
+---
+---@field oculus integer
+---
+---OpenVR.
+---
+---@field openvr integer
+---
+---OpenXR.
+---
+---@field openxr integer
+---
+---Oculus Mobile SDK.
+---
+---@field vrapi integer
+---
+---Pico.
+---
+---@field pico integer
+---
+---WebXR.
+---
+---@field webxr integer
+
+---
+---Represents the different types of origins for coordinate spaces. An origin of "floor" means that the origin is on the floor in the middle of a room-scale play area. An origin of "head" means that no positional tracking is available, and consequently the origin is always at the position of the headset.
+---
+---@class lovr.HeadsetOrigin
+---
+---The origin is at the head.
+---
+---@field head integer
+---
+---The origin is on the floor.
+---
+---@field floor integer
diff --git a/meta/3rd/lovr/library/lovr.lovr.lua b/meta/3rd/lovr/library/lovr.lovr.lua
new file mode 100644
index 00000000..6367c768
--- /dev/null
+++ b/meta/3rd/lovr/library/lovr.lovr.lua
@@ -0,0 +1,15 @@
+---@meta
+
+---
+---`lovr` is the single global table that is exposed to every LÖVR app. It contains a set of **modules** and a set of **callbacks**.
+---
+---@class lovr.lovr
+lovr.lovr = {}
+
+---
+---Get the current major, minor, and patch version of LÖVR.
+---
+---@return number major # The major version.
+---@return number minor # The minor version.
+---@return number patch # The patch number.
+function lovr.lovr.getVersion() end
diff --git a/meta/3rd/lovr/library/lovr.lua b/meta/3rd/lovr/library/lovr.lua
new file mode 100644
index 00000000..b1f3e990
--- /dev/null
+++ b/meta/3rd/lovr/library/lovr.lua
@@ -0,0 +1,101 @@
+---@meta
+
+---@class lovr
+lovr = {}
+
+---
+---The `lovr.conf` callback lets you configure default settings for LÖVR. It is called once right before the game starts. Make sure you put `lovr.conf` in a file called `conf.lua`, a special file that's loaded before the rest of the framework initializes.
+---
+---@alias lovr.conf fun(t: table)
+
+---
+---This callback is called every frame. Use it to render the scene. If a VR headset is connected, anything rendered by this function will appear in the headset display. The display is cleared to the background color before this function is called.
+---
+---@alias lovr.draw fun()
+
+---
+---The "lovr.errhand" callback is run whenever an error occurs. It receives two parameters. The first is a string containing the error message. The second is either nil, or a string containing a traceback (as returned by "debug.traceback()"); if nil, this means "lovr.errhand" is being called in the stack where the error occurred, and it can call "debug.traceback()" itself.
+---
+---"lovr.errhand" should return a handler function to run in a loop to show the error screen. This handler function is of the same type as the one returned by "lovr.run" and has the same requirements (such as pumping events). If an error occurs while this handler is running, the program will terminate immediately-- "lovr.errhand" will not be given a second chance. Errors which occur inside "lovr.errhand" or in the handler it returns may not be cleanly reported, so be careful.
+---
+---A default error handler is supplied that renders the error message as text to the headset and to the window.
+---
+---@alias lovr.errhand fun(message: string, traceback: string):function
+
+---
+---The `lovr.focus` callback is called whenever the application acquires or loses focus (for example, when opening or closing the Steam dashboard). The callback receives a single argument, focused, which is a boolean indicating whether or not the application is now focused. It may make sense to pause the game or reduce visual fidelity when the application loses focus.
+---
+---@alias lovr.focus fun(focused: boolean)
+
+---
+---This callback is called when a key is pressed.
+---
+---@alias lovr.keypressed fun(key: lovr.KeyCode, scancode: number, repeating: boolean)
+
+---
+---This callback is called when a key is released.
+---
+---@alias lovr.keyreleased fun(key: lovr.KeyCode, scancode: number)
+
+---
+---This callback is called once when the app starts. It should be used to perform initial setup work, like loading resources and initializing classes and variables.
+---
+---@alias lovr.load fun(args: table)
+
+---
+---This callback is called when a message is logged. The default implementation of this callback prints the message to the console using `print`, but it's possible to override this callback to render messages in VR, write them to a file, filter messages, and more.
+---
+---The message can have a "tag" that is a short string representing the sender, and a "level" indicating how severe the message is.
+---
+---The `t.graphics.debug` flag in `lovr.conf` can be used to get log messages from the GPU driver (tagged as `GL`). It is also possible to emit your own log messages using `lovr.event.push`.
+---
+---@alias lovr.log fun(message: string, level: string, tag: string)
+
+---
+---This callback is called every frame after rendering to the headset and is usually used to render a mirror of the headset display onto the desktop window. It can be overridden for custom mirroring behavior. For example, you could render a single eye instead of a stereo view, apply postprocessing effects, add 2D UI, or render the scene from an entirely different viewpoint for a third person camera.
+---
+---@alias lovr.mirror fun()
+
+---
+---This callback contains a permission response previously requested with `lovr.system.requestPermission`. The callback contains information on whether permission was granted or denied.
+---
+---@alias lovr.permission fun(permission: lovr.Permission, granted: boolean)
+
+---
+---This callback is called right before the application is about to quit. Use it to perform any necessary cleanup work. A truthy value can be returned from this callback to abort quitting.
+---
+---@alias lovr.quit fun():boolean
+
+---
+---This callback is called when the desktop window is resized.
+---
+---@alias lovr.resize fun(width: number, height: number)
+
+---
+---This callback is called when a restart from `lovr.event.restart` is happening. A value can be returned to send it to the next LÖVR instance, available as the `restart` key in the argument table passed to `lovr.load`. Object instances can not be used as the restart value, since they are destroyed as part of the cleanup process.
+---
+---@alias lovr.restart fun():lovr.*
+
+---
+---This callback is the main entry point for a LÖVR program. It is responsible for calling `lovr.load` and returning the main loop function.
+---
+---@alias lovr.run fun():function
+
+---
+---This callback is called when text has been entered.
+---
+---For example, when `shift + 1` is pressed on an American keyboard, `lovr.textinput` will be called with `!`.
+---
+---@alias lovr.textinput fun(text: string, code: number)
+
+---
+---The `lovr.threaderror` callback is called whenever an error occurs in a Thread. It receives the Thread object where the error occurred and an error message.
+---
+---The default implementation of this callback will call `lovr.errhand` with the error.
+---
+---@alias lovr.threaderror fun(thread: lovr.Thread, message: string)
+
+---
+---The `lovr.update` callback should be used to update your game's logic. It receives a single parameter, `dt`, which represents the amount of elapsed time between frames. You can use this value to scale timers, physics, and animations in your game so they play at a smooth, consistent speed.
+---
+---@alias lovr.update fun(dt: number)
diff --git a/meta/3rd/lovr/library/lovr.math.lua b/meta/3rd/lovr/library/lovr.math.lua
new file mode 100644
index 00000000..96a138f3
--- /dev/null
+++ b/meta/3rd/lovr/library/lovr.math.lua
@@ -0,0 +1,147 @@
+---@meta
+
+---
+---The `lovr.math` module provides math helpers commonly used for 3D applications.
+---
+---@class lovr.math
+lovr.math = {}
+
+---
+---Drains the temporary vector pool, invalidating existing temporary vectors.
+---
+---This is called automatically at the end of each frame.
+---
+function lovr.math.drain() end
+
+---
+---Converts a color from gamma space to linear space.
+---
+---@overload fun(color: table):number, number, number
+---@overload fun(x: number):number
+---@param gr number # The red component of the gamma-space color.
+---@param gg number # The green component of the gamma-space color.
+---@param gb number # The blue component of the gamma-space color.
+---@return number lr # The red component of the resulting linear-space color.
+---@return number lg # The green component of the resulting linear-space color.
+---@return number lb # The blue component of the resulting linear-space color.
+function lovr.math.gammaToLinear(gr, gg, gb) end
+
+---
+---Get the seed used to initialize the random generator.
+---
+---@return number seed # The new seed.
+function lovr.math.getRandomSeed() end
+
+---
+---Converts a color from linear space to gamma space.
+---
+---@overload fun(color: table):number, number, number
+---@overload fun(x: number):number
+---@param lr number # The red component of the linear-space color.
+---@param lg number # The green component of the linear-space color.
+---@param lb number # The blue component of the linear-space color.
+---@return number gr # The red component of the resulting gamma-space color.
+---@return number gg # The green component of the resulting gamma-space color.
+---@return number gb # The blue component of the resulting gamma-space color.
+function lovr.math.linearToGamma(lr, lg, lb) end
+
+---
+---Creates a temporary 4D matrix. This function takes the same arguments as `Mat4:set`.
+---
+function lovr.math.mat4() end
+
+---
+---Creates a new `Curve` from a list of control points.
+---
+---@overload fun(points: table):lovr.Curve
+---@overload fun(n: number):lovr.Curve
+---@param x number # The x coordinate of the first control point.
+---@param y number # The y coordinate of the first control point.
+---@param z number # The z coordinate of the first control point.
+---@return lovr.Curve curve # The new Curve.
+function lovr.math.newCurve(x, y, z) end
+
+---
+---Creates a new 4D matrix. This function takes the same arguments as `Mat4:set`.
+---
+function lovr.math.newMat4() end
+
+---
+---Creates a new quaternion. This function takes the same arguments as `Quat:set`.
+---
+function lovr.math.newQuat() end
+
+---
+---Creates a new `RandomGenerator`, which can be used to generate random numbers. If you just want some random numbers, you can use `lovr.math.random`. Individual RandomGenerator objects are useful if you need more control over the random sequence used or need a random generator isolated from other instances.
+---
+---@overload fun(seed: number):lovr.RandomGenerator
+---@overload fun(low: number, high: number):lovr.RandomGenerator
+---@return lovr.RandomGenerator randomGenerator # The new RandomGenerator.
+function lovr.math.newRandomGenerator() end
+
+---
+---Creates a new 2D vector. This function takes the same arguments as `Vec2:set`.
+---
+function lovr.math.newVec2() end
+
+---
+---Creates a new 3D vector. This function takes the same arguments as `Vec3:set`.
+---
+function lovr.math.newVec3() end
+
+---
+---Creates a new 4D vector. This function takes the same arguments as `Vec4:set`.
+---
+function lovr.math.newVec4() end
+
+---
+---Returns a 1D, 2D, 3D, or 4D perlin noise value. The number will be between 0 and 1, and it will always be 0.5 when the inputs are integers.
+---
+---@overload fun(x: number, y: number):number
+---@overload fun(x: number, y: number, z: number):number
+---@overload fun(x: number, y: number, z: number, w: number):number
+---@param x number # The x coordinate of the input.
+---@return number noise # The noise value, between 0 and 1.
+function lovr.math.noise(x) end
+
+---
+---Creates a temporary quaternion. This function takes the same arguments as `Quat:set`.
+---
+function lovr.math.quat() end
+
+---
+---Returns a uniformly distributed pseudo-random number. This function has improved randomness over Lua's `math.random` and also guarantees that the sequence of random numbers will be the same on all platforms (given the same seed).
+---
+---@overload fun(high: number):number
+---@overload fun(low: number, high: number):number
+---@return number x # A pseudo-random number.
+function lovr.math.random() end
+
+---
+---Returns a pseudo-random number from a normal distribution (a bell curve). You can control the center of the bell curve (the mean value) and the overall width (sigma, or standard deviation).
+---
+---@param sigma? number # The standard deviation of the distribution. This can be thought of how "wide" the range of numbers is or how much variability there is.
+---@param mu? number # The average value returned.
+---@return number x # A normally distributed pseudo-random number.
+function lovr.math.randomNormal(sigma, mu) end
+
+---
+---Seed the random generator with a new seed. Each seed will cause `lovr.math.random` and `lovr.math.randomNormal` to produce a unique sequence of random numbers. This is done once automatically at startup by `lovr.run`.
+---
+---@param seed number # The new seed.
+function lovr.math.setRandomSeed(seed) end
+
+---
+---Creates a temporary 2D vector. This function takes the same arguments as `Vec2:set`.
+---
+function lovr.math.vec2() end
+
+---
+---Creates a temporary 3D vector. This function takes the same arguments as `Vec3:set`.
+---
+function lovr.math.vec3() end
+
+---
+---Creates a temporary 4D vector. This function takes the same arguments as `Vec4:set`.
+---
+function lovr.math.vec4() end
diff --git a/meta/3rd/lovr/library/lovr.physics.lua b/meta/3rd/lovr/library/lovr.physics.lua
new file mode 100644
index 00000000..a1c69740
--- /dev/null
+++ b/meta/3rd/lovr/library/lovr.physics.lua
@@ -0,0 +1,142 @@
+---@meta
+
+---
+---The `lovr.physics` module simulates 3D rigid body physics.
+---
+---@class lovr.physics
+lovr.physics = {}
+
+---
+---Creates a new BallJoint.
+---
+---@param colliderA lovr.Collider # The first collider to attach the Joint to.
+---@param colliderB lovr.Collider # The second collider to attach the Joint to.
+---@param x number # The x position of the joint anchor point, in world coordinates.
+---@param y number # The y position of the joint anchor point, in world coordinates.
+---@param z number # The z position of the joint anchor point, in world coordinates.
+---@return lovr.BallJoint ball # The new BallJoint.
+function lovr.physics.newBallJoint(colliderA, colliderB, x, y, z) end
+
+---
+---Creates a new BoxShape.
+---
+---@param width? number # The width of the box, in meters.
+---@param height? number # The height of the box, in meters.
+---@param depth? number # The depth of the box, in meters.
+---@return lovr.BoxShape box # The new BoxShape.
+function lovr.physics.newBoxShape(width, height, depth) end
+
+---
+---Creates a new CapsuleShape. Capsules are cylinders with hemispheres on each end.
+---
+---@param radius? number # The radius of the capsule, in meters.
+---@param length? number # The length of the capsule, not including the caps, in meters.
+---@return lovr.CapsuleShape capsule # The new CapsuleShape.
+function lovr.physics.newCapsuleShape(radius, length) end
+
+---
+---Creates a new CylinderShape.
+---
+---@param radius? number # The radius of the cylinder, in meters.
+---@param length? number # The length of the cylinder, in meters.
+---@return lovr.CylinderShape cylinder # The new CylinderShape.
+function lovr.physics.newCylinderShape(radius, length) end
+
+---
+---Creates a new DistanceJoint.
+---
+---@param colliderA lovr.Collider # The first collider to attach the Joint to.
+---@param colliderB lovr.Collider # The second collider to attach the Joint to.
+---@param x1 number # The x position of the first anchor point, in world coordinates.
+---@param y1 number # The y position of the first anchor point, in world coordinates.
+---@param z1 number # The z position of the first anchor point, in world coordinates.
+---@param x2 number # The x position of the second anchor point, in world coordinates.
+---@param y2 number # The y position of the second anchor point, in world coordinates.
+---@param z2 number # The z position of the second anchor point, in world coordinates.
+---@return lovr.DistanceJoint joint # The new DistanceJoint.
+function lovr.physics.newDistanceJoint(colliderA, colliderB, x1, y1, z1, x2, y2, z2) end
+
+---
+---Creates a new HingeJoint.
+---
+---@param colliderA lovr.Collider # The first collider to attach the Joint to.
+---@param colliderB lovr.Collider # The second collider to attach the Joint to.
+---@param x number # The x position of the hinge anchor, in world coordinates.
+---@param y number # The y position of the hinge anchor, in world coordinates.
+---@param z number # The z position of the hinge anchor, in world coordinates.
+---@param ax number # The x component of the hinge axis.
+---@param ay number # The y component of the hinge axis.
+---@param az number # The z component of the hinge axis.
+---@return lovr.HingeJoint hinge # The new HingeJoint.
+function lovr.physics.newHingeJoint(colliderA, colliderB, x, y, z, ax, ay, az) end
+
+---
+---Creates a new SliderJoint.
+---
+---@param colliderA lovr.Collider # The first collider to attach the Joint to.
+---@param colliderB lovr.Collider # The second collider to attach the Joint to.
+---@param ax number # The x component of the slider axis.
+---@param ay number # The y component of the slider axis.
+---@param az number # The z component of the slider axis.
+---@return lovr.SliderJoint slider # The new SliderJoint.
+function lovr.physics.newSliderJoint(colliderA, colliderB, ax, ay, az) end
+
+---
+---Creates a new SphereShape.
+---
+---@param radius? number # The radius of the sphere, in meters.
+---@return lovr.SphereShape sphere # The new SphereShape.
+function lovr.physics.newSphereShape(radius) end
+
+---
+---Creates a new physics World, which tracks the overall physics simulation, holds collider objects, and resolves collisions between them.
+---
+---@param xg? number # The x component of the gravity force.
+---@param yg? number # The y component of the gravity force.
+---@param zg? number # The z component of the gravity force.
+---@param allowSleep? boolean # Whether or not colliders will automatically be put to sleep.
+---@param tags? table # A list of collision tags colliders can be assigned to.
+---@return lovr.World world # A whole new World.
+function lovr.physics.newWorld(xg, yg, zg, allowSleep, tags) end
+
+---
+---Represents the different types of physics Joints available.
+---
+---@class lovr.JointType
+---
+---A BallJoint.
+---
+---@field ball integer
+---
+---A DistanceJoint.
+---
+---@field distance integer
+---
+---A HingeJoint.
+---
+---@field hinge integer
+---
+---A SliderJoint.
+---
+---@field slider integer
+
+---
+---Represents the different types of physics Shapes available.
+---
+---@class lovr.ShapeType
+---
+---A BoxShape.
+---
+---@field box integer
+---
+---A CapsuleShape.
+---
+---@field capsule integer
+---
+---A CylinderShape.
+---
+---@field cylinder integer
+---
+---A SphereShape.
+---
+---@field sphere integer
diff --git a/meta/3rd/lovr/library/lovr.system.lua b/meta/3rd/lovr/library/lovr.system.lua
new file mode 100644
index 00000000..cd493f18
--- /dev/null
+++ b/meta/3rd/lovr/library/lovr.system.lua
@@ -0,0 +1,34 @@
+---@meta
+
+---
+---The `lovr.system` provides information about the current operating system, and platform, and hardware.
+---
+---@class lovr.system
+lovr.system = {}
+
+---
+---Returns the number of logical cores on the system.
+---
+---@return number cores # The number of logical cores on the system.
+function lovr.system.getCoreCount() end
+
+---
+---Returns the current operating system.
+---
+---@return string os # Either "Windows", "macOS", "Linux", "Android" or "Web".
+function lovr.system.getOS() end
+
+---
+---Requests permission to use a feature. Usually this will pop up a dialog box that the user needs to confirm. Once the permission request has been acknowledged, the `lovr.permission` callback will be called with the result. Currently, this is only used for requesting microphone access on Android devices.
+---
+---@param permission lovr.Permission # The permission to request.
+function lovr.system.requestPermission(permission) end
+
+---
+---These are the different permissions that need to be requested using `lovr.system.requestPermission` on some platforms.
+---
+---@class lovr.Permission
+---
+---Requests microphone access.
+---
+---@field audiocapture integer
diff --git a/meta/3rd/lovr/library/lovr.thread.lua b/meta/3rd/lovr/library/lovr.thread.lua
new file mode 100644
index 00000000..7e1218f7
--- /dev/null
+++ b/meta/3rd/lovr/library/lovr.thread.lua
@@ -0,0 +1,42 @@
+---@meta
+
+---
+---The `lovr.thread` module provides functions for creating threads and communicating between them.
+---
+---These are operating system level threads, which are different from Lua coroutines.
+---
+---Threads are useful for performing expensive background computation without affecting the framerate or performance of the main thread. Some examples of this include asset loading, networking and network requests, and physics simulation.
+---
+---Threads come with some caveats:
+---
+---- Threads run in a bare Lua environment. The `lovr` module (and any of lovr's modules) need to
+--- be required before they can be used.
+--- - To get `require` to work properly, add `require 'lovr.filesystem'` to the thread code.
+---- Threads are completely isolated from other threads. They do not have access to the variables
+--- or functions of other threads, and communication between threads must be coordinated through
+--- `Channel` objects.
+---- The graphics module (or any functions that perform rendering) cannot be used in a thread.
+--- Note that this includes creating graphics objects like Models and Textures. There are "data"
+--- equivalent `ModelData` and `Image` objects that can be used in threads though.
+---- `lovr.event.pump` cannot be called from a thread.
+---- Crashes or problems can happen if two threads access the same object at the same time, so
+--- special care must be taken to coordinate access to objects from multiple threads.
+---
+---@class lovr.thread
+lovr.thread = {}
+
+---
+---Returns a named Channel for communicating between threads.
+---
+---@param name string # The name of the Channel to get.
+---@return lovr.Channel channel # The Channel with the specified name.
+function lovr.thread.getChannel(name) end
+
+---
+---Creates a new Thread from Lua code.
+---
+---@overload fun(filename: string):lovr.Thread
+---@overload fun(blob: lovr.Blob):lovr.Thread
+---@param code string # The code to run in the Thread.
+---@return lovr.Thread thread # The new Thread.
+function lovr.thread.newThread(code) end
diff --git a/meta/3rd/lovr/library/lovr.timer.lua b/meta/3rd/lovr/library/lovr.timer.lua
new file mode 100644
index 00000000..b4693e4c
--- /dev/null
+++ b/meta/3rd/lovr/library/lovr.timer.lua
@@ -0,0 +1,43 @@
+---@meta
+
+---
+---The `lovr.timer` module provides a few functions that deal with time. All times are measured in seconds.
+---
+---@class lovr.timer
+lovr.timer = {}
+
+---
+---Returns the average delta over the last second.
+---
+---@return number delta # The average delta, in seconds.
+function lovr.timer.getAverageDelta() end
+
+---
+---Returns the time between the last two frames. This is the same value as the `dt` argument provided to `lovr.update`.
+---
+---@return number dt # The delta time, in seconds.
+function lovr.timer.getDelta() end
+
+---
+---Returns the current frames per second, averaged over the last 90 frames.
+---
+---@return number fps # The current FPS.
+function lovr.timer.getFPS() end
+
+---
+---Returns the time since some time in the past. This can be used to measure the difference between two points in time.
+---
+---@return number time # The current time, in seconds.
+function lovr.timer.getTime() end
+
+---
+---Sleeps the application for a specified number of seconds. While the game is asleep, no code will be run, no graphics will be drawn, and the window will be unresponsive.
+---
+---@param duration number # The number of seconds to sleep for.
+function lovr.timer.sleep(duration) end
+
+---
+---Steps the timer, returning the new delta time. This is called automatically in `lovr.run` and it's used to calculate the new `dt` to pass to `lovr.update`.
+---
+---@return number delta # The amount of time since the last call to this function, in seconds.
+function lovr.timer.step() end
diff --git a/tools/build-3rd-meta.lua b/tools/build-3rd-meta.lua
new file mode 100644
index 00000000..ab6b683e
--- /dev/null
+++ b/tools/build-3rd-meta.lua
@@ -0,0 +1,4 @@
+package.path = package.path .. ';script/?.lua;tools/?.lua'
+
+dofile 'tools/love-api.lua'
+dofile 'tools/lovr-api.lua'
diff --git a/tools/love-api.lua b/tools/love-api.lua
index 32ded033..90f43876 100644
--- a/tools/love-api.lua
+++ b/tools/love-api.lua
@@ -1,5 +1,4 @@
-
-package.path = package.path .. ';script/?.lua;tools/?.lua;3rd/love-api/?.lua'
+package.path = package.path .. ';3rd/love-api/?.lua'
local lua51 = require 'Lua51'
local api = lua51.require 'love_api'
diff --git a/tools/lovr-api.lua b/tools/lovr-api.lua
new file mode 100644
index 00000000..24df58b0
--- /dev/null
+++ b/tools/lovr-api.lua
@@ -0,0 +1,216 @@
+local fs = require 'bee.filesystem'
+local fsu = require 'fs-utility'
+
+local api = dofile('3rd/lovr-api/api/init.lua')
+
+local metaPath = fs.path 'meta/3rd/lovr'
+local libraryPath = metaPath / 'library'
+fs.create_directories(libraryPath)
+
+local knownTypes = {
+ ['nil'] = 'nil',
+ ['any'] = 'any',
+ ['boolean'] = 'boolean',
+ ['number'] = 'number',
+ ['integer'] = 'integer',
+ ['string'] = 'string',
+ ['table'] = 'table',
+ ['function'] = 'function',
+ ['userdata'] = 'userdata',
+ ['lightuserdata'] = 'lightuserdata',
+ ['thread'] = 'thread',
+ ['cdata'] = 'ffi.cdata*',
+ ['light userdata'] = 'lightuserdata',
+ ['Variant'] = 'any',
+}
+
+local function trim(name)
+ name = name:gsub('^%s+', '')
+ name = name:gsub('%s+$', '')
+ return name
+end
+
+---@param names string
+local function getTypeName(names)
+ local types = {}
+ names = names:gsub('%sor%s', '|')
+ for name in names:gmatch '[^|]+' do
+ name = trim(name)
+ types[#types+1] = knownTypes[name] or ('lovr.' .. name)
+ end
+ return table.concat(types, '|')
+end
+
+local function formatIndex(key)
+ if key:match '^[%a_][%w_]*$' then
+ return key
+ end
+ return ('[%q]'):format(key)
+end
+
+local buildType
+
+local function buildDocTable(tbl)
+ local fields = {}
+ for _, field in ipairs(tbl) do
+ if field.name ~= '...' then
+ fields[#fields+1] = ('%s: %s'):format(formatIndex(field.name), buildType(field))
+ end
+ end
+ return ('{%s}'):format(table.concat(fields, ', '))
+end
+
+function buildType(param)
+ if param.table then
+ return buildDocTable(param.table)
+ end
+ return getTypeName(param.type)
+end
+
+local function buildSuper(tp)
+ if not tp.supertypes then
+ return ''
+ end
+ local parents = {}
+ for _, parent in ipairs(tp.supertypes) do
+ parents[#parents+1] = getTypeName(parent)
+ end
+ return (': %s'):format(table.concat(parents, ', '))
+end
+
+local function buildDescription(desc)
+ if desc then
+ return ('---\n---%s\n---'):format(desc:gsub('([\r\n])', '%1---'))
+ else
+ return nil
+ end
+end
+
+local function buildDocFunc(variant)
+ local params = {}
+ local returns = {}
+ for _, param in ipairs(variant.arguments or {}) do
+ if param.name == '...' then
+ params[#params+1] = '...'
+ else
+ if param.name:find '^[\'"]' then
+ params[#params+1] = ('%s: %s|%q'):format(param.name:sub(2, -2), getTypeName(param.type), param.name)
+ else
+ params[#params+1] = ('%s: %s'):format(param.name, getTypeName(param.type))
+ end
+ end
+ end
+ for _, rtn in ipairs(variant.returns or {}) do
+ returns[#returns+1] = ('%s'):format(getTypeName(rtn.type))
+ end
+ return ('fun(%s)%s'):format(
+ table.concat(params, ', '),
+ #returns > 0 and (':' .. table.concat(returns, ', ')) or ''
+ )
+end
+
+local function buildMultiDocFunc(tp)
+ local cbs = {}
+ for _, variant in ipairs(tp.variants) do
+ cbs[#cbs+1] = buildDocFunc(variant)
+ end
+ return table.concat(cbs, '|')
+end
+
+local function buildFunction(func, node)
+ local text = {}
+ text[#text+1] = buildDescription(func.description)
+ for i = 2, #func.variants do
+ local variant = func.variants[i]
+ text[#text+1] = ('---@overload %s'):format(buildDocFunc(variant))
+ end
+ local params = {}
+ for _, param in ipairs(func.variants[1].arguments or {}) do
+ for paramName in param.name:gmatch '[%a_][%w_]*' do
+ params[#params+1] = paramName
+ text[#text+1] = ('---@param %s%s %s # %s'):format(
+ paramName,
+ param.default == nil and '' or '?',
+ buildType(param),
+ param.description
+ )
+ end
+ end
+ for _, rtn in ipairs(func.variants[1].returns or {}) do
+ for returnName in rtn.name:gmatch '[%a_][%w_]*' do
+ text[#text+1] = ('---@return %s %s # %s'):format(
+ buildType(rtn),
+ returnName,
+ rtn.description
+ )
+ end
+ end
+ text[#text+1] = ('function %s%s(%s) end'):format(
+ node,
+ func.name,
+ table.concat(params, ', ')
+ )
+ return table.concat(text, '\n')
+end
+
+local function buildFile(class, defs)
+ local filePath = libraryPath / (class .. '.lua')
+ local text = {}
+
+ text[#text+1] = '---@meta'
+ text[#text+1] = ''
+ text[#text+1] = buildDescription(defs.description)
+ text[#text+1] = ('---@class %s'):format(class)
+ text[#text+1] = ('%s = {}'):format(class)
+
+ for _, func in ipairs(defs.functions or {}) do
+ text[#text+1] = ''
+ text[#text+1] = buildFunction(func, class .. '.')
+ end
+
+ for _, tp in ipairs(defs.types or {}) do
+ local mark = {}
+ text[#text+1] = ''
+ text[#text+1] = buildDescription(tp.description)
+ text[#text+1] = ('---@class %s%s'):format(getTypeName(tp.name), buildSuper(tp))
+ text[#text+1] = ('local %s = {}'):format(tp.name)
+ for _, func in ipairs(tp.functions or {}) do
+ if not mark[func.name] then
+ mark[func.name] = true
+ text[#text+1] = ''
+ text[#text+1] = buildFunction(func, tp.name .. ':')
+ end
+ end
+ end
+
+ for _, cb in ipairs(defs.callbacks or {}) do
+ text[#text+1] = ''
+ text[#text+1] = buildDescription(cb.description)
+ text[#text+1] = ('---@alias %s %s'):format(getTypeName(cb.name), buildMultiDocFunc(cb))
+ end
+
+ for _, enum in ipairs(defs.enums or {}) do
+ text[#text+1] = ''
+ text[#text+1] = buildDescription(enum.description)
+ text[#text+1] = ('---@class %s'):format(getTypeName(enum.name))
+ for _, constant in ipairs(enum.values) do
+ text[#text+1] = buildDescription(constant.description)
+ text[#text+1] = ('---@field %s integer'):format(formatIndex(constant.name))
+ end
+ end
+
+ if defs.version then
+ text[#text+1] = ''
+ text[#text+1] = ('return %s'):format(class)
+ end
+
+ text[#text+1] = ''
+
+ fsu.saveFile(filePath, table.concat(text, '\n'))
+end
+
+buildFile('lovr', api)
+
+for _, module in ipairs(api.modules) do
+ buildFile('lovr.' .. module.name, module)
+end