Przeglądaj źródła

Merge branch 'dev'

bjorn 3 lat temu
rodzic
commit
9c337f0dac
100 zmienionych plików z 3378 dodań i 1651 usunięć
  1. 745 911
      api/init.lua
  2. 18 0
      api/lovr/data/AnimationProperty.lua
  3. 34 0
      api/lovr/data/AttributeType.lua
  4. 1 1
      api/lovr/data/ChannelLayout.lua
  5. 36 0
      api/lovr/data/DefaultAttribute.lua
  6. 45 0
      api/lovr/data/DrawMode.lua
  7. 1 2
      api/lovr/data/Image/init.lua
  8. 38 0
      api/lovr/data/ModelData/getAnimationChannelCount.lua
  9. 15 0
      api/lovr/data/ModelData/getAnimationCount.lua
  10. 36 0
      api/lovr/data/ModelData/getAnimationDuration.lua
  11. 46 0
      api/lovr/data/ModelData/getAnimationKeyframe.lua
  12. 38 0
      api/lovr/data/ModelData/getAnimationKeyframeCount.lua
  13. 22 0
      api/lovr/data/ModelData/getAnimationName.lua
  14. 38 0
      api/lovr/data/ModelData/getAnimationNode.lua
  15. 39 0
      api/lovr/data/ModelData/getAnimationProperty.lua
  16. 38 0
      api/lovr/data/ModelData/getAnimationSmoothMode.lua
  17. 22 0
      api/lovr/data/ModelData/getBlob.lua
  18. 16 0
      api/lovr/data/ModelData/getBlobCount.lua
  19. 46 0
      api/lovr/data/ModelData/getBoundingBox.lua
  20. 36 0
      api/lovr/data/ModelData/getBoundingSphere.lua
  21. 32 0
      api/lovr/data/ModelData/getCenter.lua
  22. 20 0
      api/lovr/data/ModelData/getDepth.lua
  23. 32 0
      api/lovr/data/ModelData/getDimensions.lua
  24. 20 0
      api/lovr/data/ModelData/getHeight.lua
  25. 22 0
      api/lovr/data/ModelData/getImage.lua
  26. 16 0
      api/lovr/data/ModelData/getImageCount.lua
  27. 171 0
      api/lovr/data/ModelData/getMaterial.lua
  28. 18 0
      api/lovr/data/ModelData/getMaterialCount.lua
  29. 24 0
      api/lovr/data/ModelData/getMaterialName.lua
  30. 15 0
      api/lovr/data/ModelData/getMeshCount.lua
  31. 21 0
      api/lovr/data/ModelData/getMeshDrawMode.lua
  32. 33 0
      api/lovr/data/ModelData/getMeshIndex.lua
  33. 22 0
      api/lovr/data/ModelData/getMeshIndexCount.lua
  34. 42 0
      api/lovr/data/ModelData/getMeshIndexFormat.lua
  35. 20 0
      api/lovr/data/ModelData/getMeshMaterial.lua
  36. 32 0
      api/lovr/data/ModelData/getMeshVertex.lua
  37. 21 0
      api/lovr/data/ModelData/getMeshVertexCount.lua
  38. 37 0
      api/lovr/data/ModelData/getMeshVertexFormat.lua
  39. 19 0
      api/lovr/data/ModelData/getMetadata.lua
  40. 38 0
      api/lovr/data/ModelData/getNodeChildren.lua
  41. 15 0
      api/lovr/data/ModelData/getNodeCount.lua
  42. 37 0
      api/lovr/data/ModelData/getNodeMeshes.lua
  43. 22 0
      api/lovr/data/ModelData/getNodeName.lua
  44. 48 0
      api/lovr/data/ModelData/getNodeOrientation.lua
  45. 35 0
      api/lovr/data/ModelData/getNodeParent.lua
  46. 60 0
      api/lovr/data/ModelData/getNodePose.lua
  47. 44 0
      api/lovr/data/ModelData/getNodePosition.lua
  48. 44 0
      api/lovr/data/ModelData/getNodeScale.lua
  49. 37 0
      api/lovr/data/ModelData/getNodeSkin.lua
  50. 74 0
      api/lovr/data/ModelData/getNodeTransform.lua
  51. 17 0
      api/lovr/data/ModelData/getRootNode.lua
  52. 19 0
      api/lovr/data/ModelData/getSkinCount.lua
  53. 23 0
      api/lovr/data/ModelData/getSkinInverseBindMatrix.lua
  54. 18 0
      api/lovr/data/ModelData/getSkinJoints.lua
  55. 21 0
      api/lovr/data/ModelData/getTriangleCount.lua
  56. 34 0
      api/lovr/data/ModelData/getTriangles.lua
  57. 20 0
      api/lovr/data/ModelData/getVertexCount.lua
  58. 20 0
      api/lovr/data/ModelData/getWidth.lua
  59. 18 0
      api/lovr/data/SmoothMode.lua
  60. 218 0
      api/lovr/data/TextureFormat.lua
  61. 0 20
      api/lovr/graphics/ArcMode.lua
  62. 0 43
      api/lovr/graphics/AttributeType.lua
  63. 0 28
      api/lovr/graphics/BlendAlphaMode.lua
  64. 0 50
      api/lovr/graphics/BlendMode.lua
  65. 0 29
      api/lovr/graphics/BlockType.lua
  66. 29 0
      api/lovr/graphics/Buffer/clear.lua
  67. 36 0
      api/lovr/graphics/Buffer/getFormat.lua
  68. 16 0
      api/lovr/graphics/Buffer/getLength.lua
  69. 19 0
      api/lovr/graphics/Buffer/getPointer.lua
  70. 16 0
      api/lovr/graphics/Buffer/getSize.lua
  71. 23 0
      api/lovr/graphics/Buffer/getStride.lua
  72. 39 0
      api/lovr/graphics/Buffer/init.lua
  73. 15 0
      api/lovr/graphics/Buffer/isTemporary.lua
  74. 97 0
      api/lovr/graphics/Buffer/setData.lua
  75. 44 0
      api/lovr/graphics/BufferLayout.lua
  76. 0 24
      api/lovr/graphics/BufferUsage.lua
  77. 0 19
      api/lovr/graphics/Canvas/getDepthTexture.lua
  78. 0 22
      api/lovr/graphics/Canvas/getDimensions.lua
  79. 0 17
      api/lovr/graphics/Canvas/getHeight.lua
  80. 0 21
      api/lovr/graphics/Canvas/getMSAA.lua
  81. 0 13
      api/lovr/graphics/Canvas/getTexture.lua
  82. 0 17
      api/lovr/graphics/Canvas/getWidth.lua
  83. 0 70
      api/lovr/graphics/Canvas/init.lua
  84. 0 20
      api/lovr/graphics/Canvas/isStereo.lua
  85. 0 28
      api/lovr/graphics/Canvas/newImage.lua
  86. 0 36
      api/lovr/graphics/Canvas/renderTo.lua
  87. 0 36
      api/lovr/graphics/Canvas/setTexture.lua
  88. 0 48
      api/lovr/graphics/CompareMode.lua
  89. 0 16
      api/lovr/graphics/CoordinateSpace.lua
  90. 0 38
      api/lovr/graphics/DefaultShader.lua
  91. 0 49
      api/lovr/graphics/DrawMode.lua
  92. 0 16
      api/lovr/graphics/DrawStyle.lua
  93. 205 0
      api/lovr/graphics/FieldType.lua
  94. 0 28
      api/lovr/graphics/FilterMode.lua
  95. 5 6
      api/lovr/graphics/Font/getAscent.lua
  96. 0 15
      api/lovr/graphics/Font/getBaseline.lua
  97. 8 6
      api/lovr/graphics/Font/getDescent.lua
  98. 8 6
      api/lovr/graphics/Font/getHeight.lua
  99. 29 0
      api/lovr/graphics/Font/getKerning.lua
  100. 0 16
      api/lovr/graphics/Font/getLineHeight.lua

Plik diff jest za duży
+ 745 - 911
api/init.lua


+ 18 - 0
api/lovr/data/AnimationProperty.lua

@@ -0,0 +1,18 @@
+return {
+  summary = 'Different animated properties.',
+  description = 'This indicates the different transform properties that can be animated.',
+  values = {
+    {
+      name = 'translation',
+      description = 'Node translation.'
+    },
+    {
+      name = 'rotation',
+      description = 'Node rotation.'
+    },
+    {
+      name = 'scale',
+      description = 'Node scale.'
+    }
+  }
+}

+ 34 - 0
api/lovr/data/AttributeType.lua

@@ -0,0 +1,34 @@
+return {
+  summary = 'Data types for vertex attributes in meshes.',
+  description = 'These are the data types that can be used by vertex data in meshes.',
+  values = {
+    {
+      name = 'i8',
+      description = 'Signed 8 bit integers (-128 to 127).'
+    },
+    {
+      name = 'u8',
+      description = 'Unsigned 8 bit integers (0 to 255).'
+    },
+    {
+      name = 'i16',
+      description = 'Signed 16 bit integers (-32768 to 32767).'
+    },
+    {
+      name = 'u16',
+      description = 'Unsigned 16 bit integers (0 to 65535).'
+    },
+    {
+      name = 'i32',
+      description = 'Signed 32 bit integers (-2147483648 to 2147483647).'
+    },
+    {
+      name = 'u32',
+      description = 'Unsigned 32 bit integers (0 to 429467295).'
+    },
+    {
+      name = 'f32',
+      description = 'Floating point numbers.'
+    }
+  }
+}

+ 1 - 1
api/lovr/data/ChannelLayout.lua

@@ -20,7 +20,7 @@ return {
       description = [[
         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.  
+        can only be loaded, not played.
       ]]
     }
   },

+ 36 - 0
api/lovr/data/DefaultAttribute.lua

@@ -0,0 +1,36 @@
+return {
+  summary = 'Attributes that can be loaded from a model.',
+  description = [[
+    These are the different types of attributes that may be present in meshes loaded from models.
+  ]],
+  values = {
+    {
+      name = 'position',
+      description = 'Vertex positions.'
+    },
+    {
+      name = 'normal',
+      description = 'Vertex normal vectors.'
+    },
+    {
+      name = 'uv',
+      description = 'Vertex texture coordinates.'
+    },
+    {
+      name = 'color',
+      description = 'Vertex colors.'
+    },
+    {
+      name = 'tangent',
+      description = 'Vertex tangent vectors.'
+    },
+    {
+      name = 'joints',
+      description = 'Vertex joint indices.'
+    },
+    {
+      name = 'weights',
+      description = 'Vertex joint weights.'
+    }
+  }
+}

+ 45 - 0
api/lovr/data/DrawMode.lua

@@ -0,0 +1,45 @@
+return {
+  summary = 'Different draw modes for meshes in ModelDatas.',
+  description = 'The DrawMode of a mesh determines how its vertices are connected together.',
+  values = {
+    {
+      name = 'points',
+      description = 'Each vertex is draw as a single point.'
+    },
+    {
+      name = 'lines',
+      description = 'Every pair of vertices is drawn as a line.'
+    },
+    {
+      name = 'linestrip',
+      description = 'Draws a single line through all of the vertices.'
+    },
+    {
+      name = 'lineloop',
+      description = [[
+        Draws a single line through all of the vertices, then connects back to the first vertex.
+      ]]
+    },
+    {
+      name = 'strip',
+      description = [[
+        Vertices are rendered as triangles.  After the first 3 vertices, each
+        subsequent vertex connects to the previous two.
+      ]]
+    },
+    {
+      name = 'triangles',
+      description = 'Every 3 vertices forms a triangle.'
+    },
+    {
+      name = 'fan',
+      description = [[
+        Vertices are rendered as triangles.  After the first 3 vertices, each
+        subsequent vertex is connected to the previous vertex and the first vertex.
+      ]]
+    }
+  },
+  related = {
+    'ModelData:getMeshDrawMode'
+  }
+}

+ 1 - 2
api/lovr/data/Image/init.lua

@@ -11,7 +11,6 @@ return {
     the raw image data.
   ]],
   constructors = {
-    'lovr.data.newImage',
-    'Canvas:newImage'
+    'lovr.data.newImage'
   }
 }

+ 38 - 0
api/lovr/data/ModelData/getAnimationChannelCount.lua

@@ -0,0 +1,38 @@
+return {
+  summary = 'Get the number of channels in an animation.',
+  description = [[
+    Returns the number of channels in an animation.
+
+    A channel is a set of keyframes for a single property of a node.
+  ]],
+  arguments = {
+    index = {
+      type = 'number',
+      description = 'The index of an animation.'
+    },
+    name = {
+      type = 'string',
+      description = 'The name of an animation.'
+    }
+  },
+  returns = {
+    count = {
+      type = 'number',
+      description = 'The number of channels in the animation.'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'index' },
+      returns = { 'count' }
+    },
+    {
+      arguments = { 'name' },
+      returns = { 'count' }
+    }
+  },
+  related = {
+    'ModelData:getAnimationNode',
+    'ModelData:getAnimationProperty'
+  }
+}

+ 15 - 0
api/lovr/data/ModelData/getAnimationCount.lua

@@ -0,0 +1,15 @@
+return {
+  summary = 'Get the number of animations in the model.',
+  description = 'Returns the number of animations in the model.',
+  arguments = {},
+  returns = {
+    {
+      name = 'count',
+      type = 'number',
+      description = 'The number of animations in the model.'
+    }
+  },
+  related = {
+    'Model:getAnimationCount'
+  }
+}

+ 36 - 0
api/lovr/data/ModelData/getAnimationDuration.lua

@@ -0,0 +1,36 @@
+return {
+  summary = 'Get the duration of an animation.',
+  description = 'Returns the duration of an animation.',
+  arguments = {
+    index = {
+      type = 'number',
+      description = 'The index of the animation.'
+    },
+    name = {
+      type = 'string',
+      description = 'The name of the animation.'
+    }
+  },
+  returns = {
+    duration = {
+      type = 'number',
+      description = 'The duration of the animation, in seconds.'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'index' },
+      returns = { 'duration' }
+    },
+    {
+      arguments = { 'name' },
+      returns = { 'duration' }
+    }
+  },
+  notes = [[
+    The duration of the animation is calculated as the latest timestamp of all of its channels.
+  ]],
+  related = {
+    'Model:getAnimationDuration'
+  }
+}

+ 46 - 0
api/lovr/data/ModelData/getAnimationKeyframe.lua

@@ -0,0 +1,46 @@
+return {
+  summary = 'Get a keyframe in a channel of an animation.',
+  description = 'Returns a single keyframe in a channel of an animation.',
+  arguments = {
+    index = {
+      type = 'number',
+      description = 'The index of an animation.'
+    },
+    name = {
+      type = 'string',
+      description = 'The name of an animation.'
+    },
+    channel = {
+      type = 'number',
+      description = 'The index of a channel in the animation.'
+    },
+    keyframe = {
+      type = 'number',
+      description = 'The index of a keyframe in the channel.'
+    }
+  },
+  returns = {
+    time = {
+      type = 'number',
+      description = 'The timestamp of the keyframe.'
+    },
+    ['...'] = {
+      type = 'number',
+      description = 'The data for the keyframe (either 3 or 4 numbers depending on the property).'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'index', 'channel', 'keyframe' },
+      returns = { 'time', '...' }
+    },
+    {
+      arguments = { 'name', 'channel', 'keyframe' },
+      returns = { 'time', '...' }
+    }
+  },
+  related = {
+    'ModelData:getAnimationSmoothMode',
+    'ModelData:getAnimationKeyframeCount'
+  }
+}

+ 38 - 0
api/lovr/data/ModelData/getAnimationKeyframeCount.lua

@@ -0,0 +1,38 @@
+return {
+  summary = 'Get the number of keyframes in a channel of an animation.',
+  description = 'Returns the number of keyframes in a channel of an animation.',
+  arguments = {
+    index = {
+      type = 'number',
+      description = 'The index of an animation.'
+    },
+    name = {
+      type = 'string',
+      description = 'The name of an animation.'
+    },
+    channel = {
+      type = 'number',
+      description = 'The index of a channel in the animation.'
+    }
+  },
+  returns = {
+    count = {
+      type = 'number',
+      description = 'The number of keyframes in the channel.'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'index', 'channel' },
+      returns = { 'count' }
+    },
+    {
+      arguments = { 'name', 'channel' },
+      returns = { 'count' }
+    }
+  },
+  related = {
+    'ModelData:getAnimationSmoothMode',
+    'ModelData:getAnimationKeyframe'
+  }
+}

+ 22 - 0
api/lovr/data/ModelData/getAnimationName.lua

@@ -0,0 +1,22 @@
+return {
+  summary = 'Get the name of an animation.',
+  description = 'Returns the name of an animation.',
+  arguments = {
+    {
+      name = 'index',
+      type = 'number',
+      description = 'The index of the animation.'
+    }
+  },
+  returns = {
+    {
+      name = 'name',
+      type = 'string',
+      description = 'The name of the animation.'
+    }
+  },
+  notes = 'If the animation does not have a name, this function returns `nil`.',
+  related = {
+    'Model:getAnimationName'
+  }
+}

+ 38 - 0
api/lovr/data/ModelData/getAnimationNode.lua

@@ -0,0 +1,38 @@
+return {
+  summary = 'Get the node targeted by the channel of an animation.',
+  description = 'Returns the index of a node targeted by an animation\'s channel.',
+  arguments = {
+    index = {
+      type = 'number',
+      description = 'The index of an animation.'
+    },
+    name = {
+      type = 'string',
+      description = 'The name of an animation.'
+    },
+    channel = {
+      type = 'number',
+      description = 'The index of a channel in the animation.'
+    }
+  },
+  returns = {
+    node = {
+      type = 'number',
+      description = 'The index of the node targeted by the channel.'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'index', 'channel' },
+      returns = { 'node' }
+    },
+    {
+      arguments = { 'name', 'channel' },
+      returns = { 'node' }
+    }
+  },
+  related = {
+    'ModelData:getAnimationNode',
+    'ModelData:getAnimationProperty'
+  }
+}

+ 39 - 0
api/lovr/data/ModelData/getAnimationProperty.lua

@@ -0,0 +1,39 @@
+return {
+  summary = 'Get the property targeted by the channel of an animation.',
+  description = 'Returns the property targeted by an animation\'s channel.',
+  arguments = {
+    index = {
+      type = 'number',
+      description = 'The index of an animation.'
+    },
+    name = {
+      type = 'string',
+      description = 'The name of an animation.'
+    },
+    channel = {
+      type = 'number',
+      description = 'The index of a channel in the animation.'
+    }
+  },
+  returns = {
+    property = {
+      type = 'AnimationProperty',
+      description = 'The property (translation, rotation, scale) affected by the keyframes.'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'index', 'channel' },
+      returns = { 'property' }
+    },
+    {
+      arguments = { 'name', 'channel' },
+      returns = { 'property' }
+    }
+  },
+  related = {
+    'ModelData:getAnimationNode',
+    'ModelData:getAnimationProperty',
+    'ModelData:getAnimationSmoothMode'
+  }
+}

+ 38 - 0
api/lovr/data/ModelData/getAnimationSmoothMode.lua

@@ -0,0 +1,38 @@
+return {
+  summary = 'Get the smooth mode of a channel in an animation.',
+  description = 'Returns the smooth mode of a channel in an animation.',
+  arguments = {
+    index = {
+      type = 'number',
+      description = 'The index of an animation.'
+    },
+    name = {
+      type = 'string',
+      description = 'The name of an animation.'
+    },
+    channel = {
+      type = 'number',
+      description = 'The index of a channel in the animation.'
+    }
+  },
+  returns = {
+    smooth = {
+      type = 'SmoothMode',
+      description = 'The smooth mode of the keyframes.'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'index', 'channel' },
+      returns = { 'smooth' }
+    },
+    {
+      arguments = { 'name', 'channel' },
+      returns = { 'smooth' }
+    }
+  },
+  related = {
+    'ModelData:getAnimationNode',
+    'ModelData:getAnimationProperty'
+  }
+}

+ 22 - 0
api/lovr/data/ModelData/getBlob.lua

@@ -0,0 +1,22 @@
+return {
+  summary = 'Get a Blob in the model.',
+  description = 'Returns one of the Blobs in the model, by index.',
+  arguments = {
+    {
+      name = 'index',
+      type = 'number',
+      description = 'The index of the Blob to get.'
+    }
+  },
+  returns = {
+    {
+      name = 'blob',
+      type = 'Blob',
+      description = 'The Blob object.'
+    }
+  },
+  related = {
+    'ModelData:getBlobCount',
+    'ModelData:getImage'
+  }
+}

+ 16 - 0
api/lovr/data/ModelData/getBlobCount.lua

@@ -0,0 +1,16 @@
+return {
+  summary = 'Get the number of Blobs stored in the model.',
+  description = 'Returns the number of Blobs in the model.',
+  arguments = {},
+  returns = {
+    {
+      name = 'count',
+      type = 'number',
+      description = 'The number of Blobs in the model.'
+    }
+  },
+  related = {
+    'ModelData:getBlob',
+    'ModelData:getImageCount'
+  }
+}

+ 46 - 0
api/lovr/data/ModelData/getBoundingBox.lua

@@ -0,0 +1,46 @@
+return {
+  summary = 'Get the bounding box of the model.',
+  description = 'Returns the 6 values of the model\'s axis-aligned bounding box.',
+  arguments = {},
+  returns = {
+    {
+      name = 'minx',
+      type = 'number',
+      description = 'The minimum x coordinate of the vertices in the model.'
+    },
+    {
+      name = 'maxx',
+      type = 'number',
+      description = 'The maximum x coordinate of the vertices in the model.'
+    },
+    {
+      name = 'miny',
+      type = 'number',
+      description = 'The minimum y coordinate of the vertices in the model.'
+    },
+    {
+      name = 'maxy',
+      type = 'number',
+      description = 'The maximum y coordinate of the vertices in the model.'
+    },
+    {
+      name = 'minz',
+      type = 'number',
+      description = 'The minimum z coordinate of the vertices in the model.'
+    },
+    {
+      name = 'maxz',
+      type = 'number',
+      description = 'The maximum z coordinate of the vertices in the model.'
+    }
+  },
+  related = {
+    'ModelData:getWidth',
+    'ModelData:getHeight',
+    'ModelData:getDepth',
+    'ModelData:getDimensions',
+    'ModelData:getCenter',
+    'ModelData:getBoundingSphere',
+    'Model:getBoundingBox'
+  }
+}

+ 36 - 0
api/lovr/data/ModelData/getBoundingSphere.lua

@@ -0,0 +1,36 @@
+return {
+  summary = 'Get the bounding sphere of the model.',
+  description = 'Returns a sphere approximately enclosing the vertices in the model.',
+  arguments = {},
+  returns = {
+    {
+      name = 'x',
+      type = 'number',
+      description = 'The x coordinate of the position of the sphere.'
+    },
+    {
+      name = 'y',
+      type = 'number',
+      description = 'The y coordinate of the position of the sphere.'
+    },
+    {
+      name = 'z',
+      type = 'number',
+      description = 'The z coordinate of the position of the sphere.'
+    },
+    {
+      name = 'radius',
+      type = 'number',
+      description = 'The radius of the bounding sphere.'
+    }
+  },
+  related = {
+    'ModelData:getWidth',
+    'ModelData:getHeight',
+    'ModelData:getDepth',
+    'ModelData:getDimensions',
+    'ModelData:getCenter',
+    'ModelData:getBoundingBox',
+    'Model:getBoundingSphere'
+  }
+}

+ 32 - 0
api/lovr/data/ModelData/getCenter.lua

@@ -0,0 +1,32 @@
+return {
+  summary = 'Get the center of the model\'s bounding box.',
+  description = [[
+    Returns the center of the model's axis-aligned bounding box, relative to the model's origin.
+  ]],
+  arguments = {},
+  returns = {
+    {
+      name = 'x',
+      type = 'number',
+      description = 'The x offset of the center of the bounding box.'
+    },
+    {
+      name = 'y',
+      type = 'number',
+      description = 'The y offset of the center of the bounding box.'
+    },
+    {
+      name = 'z',
+      type = 'number',
+      description = 'The z offset of the center of the bounding box.'
+    }
+  },
+  related = {
+    'ModelData:getWidth',
+    'ModelData:getHeight',
+    'ModelData:getDepth',
+    'ModelData:getDimensions',
+    'ModelData:getBoundingBox',
+    'Model:getCenter'
+  }
+}

+ 20 - 0
api/lovr/data/ModelData/getDepth.lua

@@ -0,0 +1,20 @@
+return {
+  summary = 'Get the depth of the model.',
+  description = 'Returns the depth of the model, computed from its axis-aligned bounding box.',
+  arguments = {},
+  returns = {
+    {
+      name = 'depth',
+      type = 'number',
+      description = 'The depth of the model.'
+    }
+  },
+  related = {
+    'ModelData:getWidth',
+    'ModelData:getHeight',
+    'ModelData:getDimensions',
+    'ModelData:getCenter',
+    'ModelData:getBoundingBox',
+    'Model:getDepth'
+  }
+}

+ 32 - 0
api/lovr/data/ModelData/getDimensions.lua

@@ -0,0 +1,32 @@
+return {
+  summary = 'Get the dimensions of the model.',
+  description = [[
+    Returns the width, height, and depth of the model, computed from its axis-aligned bounding box.
+  ]],
+  arguments = {},
+  returns = {
+    {
+      name = 'width',
+      type = 'number',
+      description = 'The width of the model.'
+    },
+    {
+      name = 'height',
+      type = 'number',
+      description = 'The height of the model.'
+    },
+    {
+      name = 'depth',
+      type = 'number',
+      description = 'The depth of the model.'
+    }
+  },
+  related = {
+    'ModelData:getWidth',
+    'ModelData:getHeight',
+    'ModelData:getDepth',
+    'ModelData:getCenter',
+    'ModelData:getBoundingBox',
+    'Model:getDimensions'
+  }
+}

+ 20 - 0
api/lovr/data/ModelData/getHeight.lua

@@ -0,0 +1,20 @@
+return {
+  summary = 'Get the height of the model.',
+  description = 'Returns the height of the model, computed from its axis-aligned bounding box.',
+  arguments = {},
+  returns = {
+    {
+      name = 'height',
+      type = 'number',
+      description = 'The height of the model.'
+    }
+  },
+  related = {
+    'ModelData:getWidth',
+    'ModelData:getDepth',
+    'ModelData:getDimensions',
+    'ModelData:getCenter',
+    'ModelData:getBoundingBox',
+    'Model:getHeight'
+  }
+}

+ 22 - 0
api/lovr/data/ModelData/getImage.lua

@@ -0,0 +1,22 @@
+return {
+  summary = 'Get an Image in the model.',
+  description = 'Returns one of the Images in the model, by index.',
+  arguments = {
+    {
+      name = 'index',
+      type = 'number',
+      description = 'The index of the Image to get.'
+    }
+  },
+  returns = {
+    {
+      name = 'image',
+      type = 'Image',
+      description = 'The Image object.'
+    }
+  },
+  related = {
+    'ModelData:getImageCount',
+    'ModelData:getBlob'
+  }
+}

+ 16 - 0
api/lovr/data/ModelData/getImageCount.lua

@@ -0,0 +1,16 @@
+return {
+  summary = 'Get the number of Images stored in the model.',
+  description = 'Returns the number of Images in the model.',
+  arguments = {},
+  returns = {
+    {
+      name = 'count',
+      type = 'number',
+      description = 'The number of Images in the model.'
+    }
+  },
+  related = {
+    'ModelData:getImage',
+    'ModelData:getBlobCount'
+  }
+}

+ 171 - 0
api/lovr/data/ModelData/getMaterial.lua

@@ -0,0 +1,171 @@
+return {
+  summary = 'Get the material properties for a material in the model.',
+  description = 'Returns a table with all of the properties of a material.',
+  arguments = {
+    index = {
+      type = 'number',
+      description = 'The index of a material.'
+    },
+    name = {
+      type = 'string',
+      description = 'The name of a material.'
+    }
+  },
+  returns = {
+    properties = {
+      type = 'table',
+      description = 'The material properties.',
+      table = {
+        {
+          name = 'color',
+          type = 'table',
+          description = [[
+            The color of the material.  The table contains the `r`, `g`, `b`, and `a` components of the color,
+            from 0 to 1.
+          ]]
+        },
+        {
+          name = 'glow',
+          type = 'table',
+          description = [[
+            The glow color of the material (sometimes called emissive).  The table contains the `r`,
+            `g`, and `b` components of the color from 0 to 1, and a fourth number indicating the
+            strength of the glow.
+          ]]
+        },
+        {
+          name = 'uvShift',
+          type = 'table',
+          description = 'A table with 2 numbers indicating an offset to apply to UVs.'
+        },
+        {
+          name = 'uvScale',
+          type = 'table',
+          description = [[
+            A table with 2 numbers indicating a scale to apply to UVs.  By default, shaders apply
+            the UV scale before the UV offset.
+          ]]
+        },
+        {
+          name = 'metalness',
+          type = 'number',
+          description = [[
+            The metalness parameter of the material.  This is typically 0 or 1.  By default, shaders
+            multiply this property with the value from the metalness texture (when present) to get
+            the final metalness used for shading.
+          ]]
+        },
+        {
+          name = 'roughness',
+          type = 'number',
+          description = [[
+            The roughness parameter of the material.  By default, shaders multiply this property
+            with the value from the roughness texture (when present) to get the final roughness used
+            for shading.
+          ]]
+        },
+        {
+          name = 'clearcoat',
+          type = 'number',
+          description = 'The clearcoat parameter of the material.'
+        },
+        {
+          name = 'clearcoatRoughness',
+          type = 'number',
+          description = 'The roughness of the clearcoat layer.'
+        },
+        {
+          name = 'occlusionStrength',
+          type = 'number',
+          description = [[
+            A number multiplied by the value from the ambient occlusion texture to control how
+            strong the occlusion effect is.
+          ]]
+        },
+        {
+          name = 'normalScale',
+          type = 'number',
+          description = [[
+            A number multiplied by the value from the normal texture to control how strong the
+            normal mapping effect is.
+          ]]
+        },
+        {
+          name = 'alphaCutoff',
+          type = 'number',
+          description = [[
+            If a pixel has an alpha value less than the alpha cutoff, it will be discarded, which
+            prevents it from occluding things behind it.  This is sometimes called "holepunch" or
+            "cutout" alpha.  It's useful for textures with transparency.
+          ]]
+        },
+        {
+          name = 'texture',
+          type = 'number',
+          description = 'The index of the Image used for the color texture.',
+        },
+        {
+          name = 'glowTexture',
+          type = 'number',
+          description = 'The index of the Image used for the glow texture.',
+        },
+        {
+          name = 'occlusionTexture',
+          type = 'number',
+          description = [[
+            The index of the Image used for the ambient occlusion texture.  The red channel of the
+            texture is used for ambient occlusion, allowing multiple parameters to use the same
+            texture.
+          ]]
+        },
+        {
+          name = 'metalnessTexture',
+          type = 'number',
+          description = [[
+            The index of the Image used for the metalness texture.  The blue channel of the texture
+            is used for metalness, allowing multiple parameters to use the same texture.
+          ]]
+        },
+        {
+          name = 'roughnessTexture',
+          type = 'number',
+          description = [[
+            The index of the Image to use for the roughness texture.  The green channel of the
+            texture is used for roughness, allowing multiple parameters to use the same texture.
+          ]]
+        },
+        {
+          name = 'clearcoatTexture',
+          type = 'number',
+          description = [[
+            The index of the Image to use for the clearcoat texture.  The red channel of the texture
+            is used for the clearcoat parameter, allowing multiple parameters to use the same
+            texture.
+          ]]
+        },
+        {
+          name = 'normalTexture',
+          type = 'number',
+          description = 'The index of the Image to use for the normal map.'
+        }
+      }
+    }
+  },
+  variants = {
+    {
+      arguments = { 'index' },
+      returns = { 'properties' }
+    },
+    {
+      arguments = { 'name' },
+      returns = { 'properties' }
+    }
+  },
+  notes = 'All images are optional and may be `nil`.',
+  related = {
+    'ModelData:getMaterialCount',
+    'ModelData:getMeshMaterial',
+    'lovr.graphics.newMaterial',
+    'Model:getMaterial'
+  }
+}

+ 18 - 0
api/lovr/data/ModelData/getMaterialCount.lua

@@ -0,0 +1,18 @@
+return {
+  summary = 'Get the number of materials in the model.',
+  description = 'Returns the number of materials in the model.',
+  arguments = {},
+  returns = {
+    {
+      name = 'count',
+      type = 'number',
+      description = 'The number of materials in the model.'
+    }
+  },
+  related = {
+    'ModelData:getMaterialName',
+    'ModelData:getMeshMaterial',
+    'ModelData:getMaterial',
+    'Model:getMaterialCount'
+  }
+}

+ 24 - 0
api/lovr/data/ModelData/getMaterialName.lua

@@ -0,0 +1,24 @@
+return {
+  summary = 'Get the name of a material in the model.',
+  description = 'Returns the name of a material in the model.',
+  arguments = {
+    {
+      name = 'index',
+      type = 'number',
+      description = 'The index of a material.'
+    }
+  },
+  returns = {
+    {
+      name = 'name',
+      type = 'string',
+      description = 'The name of the material, or nil if the material does not have a name.'
+    }
+  },
+  related = {
+    'ModelData:getMaterialCount',
+    'ModelData:getMeshMaterial',
+    'ModelData:getMaterial',
+    'Model:getMaterialName'
+  }
+}

+ 15 - 0
api/lovr/data/ModelData/getMeshCount.lua

@@ -0,0 +1,15 @@
+return {
+  summary = 'Get the number of meshes in the model.',
+  description = 'Returns the number of meshes in the model.',
+  arguments = {},
+  returns = {
+    {
+      name = 'count',
+      type = 'number',
+      description = 'The number of meshes in the model.'
+    }
+  },
+  related = {
+    'ModelData:getNodeMeshes'
+  }
+}

+ 21 - 0
api/lovr/data/ModelData/getMeshDrawMode.lua

@@ -0,0 +1,21 @@
+return {
+  summary = 'Get the draw mode of a mesh.',
+  description = [[
+    Returns the draw mode of a mesh.  This controls how its vertices are connected together (points,
+    lines, or triangles).
+  ]],
+  arguments = {
+    {
+      name = 'mesh',
+      type = 'number',
+      description = 'The index of a mesh.'
+    }
+  },
+  returns = {
+    {
+      name = 'mode',
+      type = 'DrawMode',
+      description = 'The draw mode of the mesh.'
+    }
+  }
+}

+ 33 - 0
api/lovr/data/ModelData/getMeshIndex.lua

@@ -0,0 +1,33 @@
+return {
+  summary = 'Get one of the vertex indices in a mesh.',
+  description = [[
+    Returns one of the vertex indices in a mesh.  If a mesh has vertex indices, they define the
+    order and connectivity of the vertices in the mesh, allowing a vertex to be reused multiple
+    times without duplicating its data.
+  ]],
+  arguments = {
+    {
+      name = 'mesh',
+      type = 'number',
+      description = 'The index of a mesh to get the vertex from.'
+    },
+    {
+      name = 'index',
+      type = 'number',
+      description = 'The index of a vertex index in the mesh to retrieve.'
+    }
+  },
+  returns = {
+    {
+      name = 'vertexindex',
+      type = 'number',
+      description = 'The vertex index.  Like all indices in Lua, this is 1-indexed.'
+    }
+  },
+  related = {
+    'ModelData:getMeshIndexFormat',
+    'ModelData:getMeshIndexCount',
+    'ModelData:getMeshVertex',
+    'ModelData:getTriangles'
+  }
+}

+ 22 - 0
api/lovr/data/ModelData/getMeshIndexCount.lua

@@ -0,0 +1,22 @@
+return {
+  summary = 'Get the number of vertex indices in a mesh.',
+  description = [[
+    Returns the number of vertex indices in a mesh.  Vertex indices allow for vertices to be reused
+    when defining triangles.
+  ]],
+  arguments = {
+    {
+      name = 'mesh',
+      type = 'number',
+      description = 'The index of a mesh.'
+    }
+  },
+  returns = {
+    {
+      name = 'count',
+      type = 'number',
+      description = 'The number of vertex indices in the mesh.'
+    }
+  },
+  notes = 'This may return zero if the mesh does not use indices.'
+}

+ 42 - 0
api/lovr/data/ModelData/getMeshIndexFormat.lua

@@ -0,0 +1,42 @@
+return {
+  summary = 'Get the data format of vertex indices in a mesh.',
+  description = [[
+    Returns the data format of vertex indices in a mesh.  If a mesh doesn't use vertex indices, this
+    function returns nil.
+  ]],
+  arguments = {
+    {
+      name = 'mesh',
+      type = 'number',
+      description = 'The index of a mesh.'
+    }
+  },
+  returns = {
+    {
+      name = 'type',
+      type = 'AttributeType',
+      description = 'The data type of each vertex index (always u16 or u32).'
+    },
+    {
+      name = 'blob',
+      type = 'number',
+      description = 'The index of a Blob in the mesh where the binary data is stored.'
+    },
+    {
+      name = 'offset',
+      type = 'number',
+      description = 'A byte offset into the Blob\'s data where the index data starts.'
+    },
+    {
+      name = 'stride',
+      type = 'number',
+      description = [[
+        The number of bytes between subsequent vertex indices.  Indices are always tightly packed,
+        so this will always be 2 or 4 depending on the data type.
+      ]]
+    }
+  },
+  related = {
+    'ModelData:getMeshVertexFormat'
+  }
+}

+ 20 - 0
api/lovr/data/ModelData/getMeshMaterial.lua

@@ -0,0 +1,20 @@
+return {
+  summary = 'Get the index of the material applied to a mesh.',
+  description = 'Returns the index of the material applied to a mesh.',
+  arguments = {
+    {
+      name = 'mesh',
+      type = 'number',
+      description = 'The index of a mesh.'
+    }
+  },
+  returns = {
+    {
+      name = 'material',
+      type = 'number',
+      description = [[
+        The index of the material applied to the mesh, or nil if the mesh does not have a material.
+      ]]
+    }
+  }
+}

+ 32 - 0
api/lovr/data/ModelData/getMeshVertex.lua

@@ -0,0 +1,32 @@
+return {
+  summary = 'Get the data for a single vertex in a mesh.',
+  description = [[
+    Returns the data for a single vertex in a mesh.  The data returned depends on the vertex format
+    of a mesh, which is given by `ModelData:getMeshVertexFormat`.
+  ]],
+  arguments = {
+    {
+      name = 'mesh',
+      type = 'number',
+      description = 'The index of a mesh to get the vertex from.'
+    },
+    {
+      name = 'vertex',
+      type = 'number',
+      description = 'The index of a vertex in the mesh to retrieve.'
+    }
+  },
+  returns = {
+    {
+      name = '...',
+      type = 'number',
+      description = 'The data for all of the attributes of the vertex.'
+    }
+  },
+  related = {
+    'ModelData:getMeshVertexFormat',
+    'ModelData:getMeshVertexCount',
+    'ModelData:getMeshIndex',
+    'ModelData:getTriangles'
+  }
+}

+ 21 - 0
api/lovr/data/ModelData/getMeshVertexCount.lua

@@ -0,0 +1,21 @@
+return {
+  summary = 'Get the number of vertices in a mesh.',
+  description = 'Returns the number of vertices in a mesh.',
+  arguments = {
+    {
+      name = 'mesh',
+      type = 'number',
+      description = 'The index of a mesh.'
+    }
+  },
+  returns = {
+    {
+      name = 'count',
+      type = 'number',
+      description = 'The number of vertices in the mesh.'
+    }
+  },
+  related = {
+    'ModelData:getMeshIndexCount'
+  }
+}

+ 37 - 0
api/lovr/data/ModelData/getMeshVertexFormat.lua

@@ -0,0 +1,37 @@
+return {
+  summary = 'Get the vertex format of a mesh.',
+  description = [[
+    Returns the vertex format of a mesh.  The vertex format defines the properties associated with
+    each vertex (position, color, etc.), including their types and binary data layout.
+  ]],
+  arguments = {
+    {
+      name = 'mesh',
+      type = 'number',
+      description = 'The index of a mesh.'
+    }
+  },
+  returns = {
+    {
+      name = 'format',
+      type = 'table',
+      description = 'The vertex format of the mesh.'
+    }
+  },
+  notes = [[
+    The format is given as a table of vertex attributes.  Each attribute is a table containing the
+    following:
+
+        { name, type, components, blob, offset, stride }
+
+    - The `name` will be a `DefaultAttribute`.
+    - The `type` will be an `AttributeType`.
+    - The `component` count will be 1-4.
+    - The `blob` is an index of one of the Blobs in the model (see `ModelData:getBlob`).
+    - The `offset` is a byte offset from the start of the Blob where the attribute's data starts.
+    - The `stride` is the number of bytes between consecutive values.
+  ]],
+  related = {
+    'ModelData:getIndexFormat'
+  }
+}

+ 19 - 0
api/lovr/data/ModelData/getMetadata.lua

@@ -0,0 +1,19 @@
+return {
+  summary = 'Get extra information from the model file.',
+  description = [[
+    Returns extra information stored in the model file.  Currently this is only implemented for glTF
+    models and returns the JSON string from the glTF or glb file.  The metadata can be used to get
+    application-specific data or add support for glTF extensions not supported by LÖVR.
+  ]],
+  arguments = {},
+  returns = {
+    {
+      name = 'metadata',
+      type = 'string',
+      description = 'The metadata from the model file.'
+    }
+  },
+  related = {
+    'Model:getMetadata'
+  }
+}

+ 38 - 0
api/lovr/data/ModelData/getNodeChildren.lua

@@ -0,0 +1,38 @@
+return {
+  summary = 'Get the children of a node.',
+  description = [[
+    Given a parent node, this function returns a table with the indices of its children.
+  ]],
+  arguments = {
+    index = {
+      type = 'number',
+      description = 'The index of the parent node.'
+    },
+    name = {
+      type = 'string',
+      description = 'The name of the parent node.'
+    }
+  },
+  returns = {
+    children = {
+      type = 'table',
+      description = 'A table containing a node index for each child of the node.'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'index' },
+      returns = { 'children' }
+    },
+    {
+      arguments = { 'name' },
+      returns = { 'children' }
+    }
+  },
+  notes = 'If the node does not have any children, this function returns an empty table.',
+  related = {
+    'ModelData:getNodeParent',
+    'ModelData:getRootNode',
+    'Model:getNodeChildren'
+  }
+}

+ 15 - 0
api/lovr/data/ModelData/getNodeCount.lua

@@ -0,0 +1,15 @@
+return {
+  summary = 'Get the number of nodes in the model.',
+  description = 'Returns the number of nodes in the model.',
+  arguments = {},
+  returns = {
+    {
+      name = 'count',
+      type = 'number',
+      description = 'The number of nodes in the model.'
+    }
+  },
+  related = {
+    'Model:getNodeCount'
+  }
+}

+ 37 - 0
api/lovr/data/ModelData/getNodeMeshes.lua

@@ -0,0 +1,37 @@
+return {
+  summary = 'Get the indices of meshes attached to a node.',
+  description = [[
+    Returns a table of mesh indices attached to a node.  Meshes define the geometry and materials of
+    a model, as opposed to the nodes which define the transforms and hierarchy.  A node can have
+    multiple meshes, and meshes can be reused in multiple nodes.
+  ]],
+  arguments = {
+    index = {
+      type = 'number',
+      description = 'The index of the node.'
+    },
+    name = {
+      type = 'string',
+      description = 'The name of the node.'
+    }
+  },
+  returns = {
+    meshes = {
+      type = 'table',
+      description = 'A table with the node\'s mesh indices.'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'index' },
+      returns = { 'meshes' }
+    },
+    {
+      arguments = { 'name' },
+      returns = { 'meshes' }
+    }
+  },
+  related = {
+    'ModelData:getMeshCount'
+  }
+}

+ 22 - 0
api/lovr/data/ModelData/getNodeName.lua

@@ -0,0 +1,22 @@
+return {
+  summary = 'Get the name of a node.',
+  description = 'Returns the name of a node.',
+  arguments = {
+    {
+      name = 'index',
+      type = 'number',
+      description = 'The index of the node.'
+    }
+  },
+  returns = {
+    {
+      name = 'name',
+      type = 'string',
+      description = 'The name of the node.'
+    }
+  },
+  notes = 'If the node does not have a name, this function returns `nil`.',
+  related = {
+    'Model:getNodeName'
+  }
+}

+ 48 - 0
api/lovr/data/ModelData/getNodeOrientation.lua

@@ -0,0 +1,48 @@
+return {
+  summary = 'Get the local orientation of a node.',
+  description = 'Returns local orientation of a node, relative to its parent.',
+  arguments = {
+    index = {
+      type = 'number',
+      description = 'The index of the node.'
+    },
+    name = {
+      type = 'string',
+      description = 'The name of the node.'
+    }
+  },
+  returns = {
+    angle = {
+      type = 'number',
+      description = 'The number of radians the node is rotated around its axis of rotation.'
+    },
+    ax = {
+      type = 'number',
+      description = 'The x component of the axis of rotation.'
+    },
+    ay = {
+      type = 'number',
+      description = 'The y component of the axis of rotation.'
+    },
+    az = {
+      type = 'number',
+      description = 'The z component of the axis of rotation.'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'index' },
+      returns = { 'angle', 'ax', 'ay', 'az' }
+    },
+    {
+      arguments = { 'name' },
+      returns = { 'angle', 'ax', 'ay', 'az' }
+    }
+  },
+  related = {
+    'ModelData:getNodePosition',
+    'ModelData:getNodeScale',
+    'ModelData:getNodePose',
+    'ModelData:getNodeTransform'
+  }
+}

+ 35 - 0
api/lovr/data/ModelData/getNodeParent.lua

@@ -0,0 +1,35 @@
+return {
+  summary = 'Get the parent of a node.',
+  description = 'Given a child node, this function returns the index of its parent.',
+  arguments = {
+    index = {
+      type = 'number',
+      description = 'The index of the child node.'
+    },
+    name = {
+      type = 'string',
+      description = 'The name of the child node.'
+    }
+  },
+  returns = {
+    parent = {
+      type = 'number',
+      description = 'The index of the parent.'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'index' },
+      returns = { 'parent' }
+    },
+    {
+      arguments = { 'name' },
+      returns = { 'parent' }
+    }
+  },
+  related = {
+    'ModelData:getNodeChildren',
+    'ModelData:getRootNode',
+    'Model:getNodeParent'
+  }
+}

+ 60 - 0
api/lovr/data/ModelData/getNodePose.lua

@@ -0,0 +1,60 @@
+return {
+  summary = 'Get the local pose of a node.',
+  description = 'Returns local pose (position and orientation) of a node, relative to its parent.',
+  arguments = {
+    index = {
+      type = 'number',
+      description = 'The index of the node.'
+    },
+    name = {
+      type = 'string',
+      description = 'The name of the node.'
+    }
+  },
+  returns = {
+    x = {
+      type = 'number',
+      description = 'The x coordinate.'
+    },
+    y = {
+      type = 'number',
+      description = 'The y coordinate.'
+    },
+    z = {
+      type = 'number',
+      description = 'The z coordinate.'
+    },
+    angle = {
+      type = 'number',
+      description = 'The number of radians the node is rotated around its axis of rotation.'
+    },
+    ax = {
+      type = 'number',
+      description = 'The x component of the axis of rotation.'
+    },
+    ay = {
+      type = 'number',
+      description = 'The y component of the axis of rotation.'
+    },
+    az = {
+      type = 'number',
+      description = 'The z component of the axis of rotation.'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'index' },
+      returns = { 'x', 'y', 'z', 'angle', 'ax', 'ay', 'az' }
+    },
+    {
+      arguments = { 'name' },
+      returns = { 'x', 'y', 'z', 'angle', 'ax', 'ay', 'az' }
+    }
+  },
+  related = {
+    'ModelData:getNodePosition',
+    'ModelData:getNodeOrientation',
+    'ModelData:getNodeScale',
+    'ModelData:getNodeTransform'
+  }
+}

+ 44 - 0
api/lovr/data/ModelData/getNodePosition.lua

@@ -0,0 +1,44 @@
+return {
+  summary = 'Get the local position of a node.',
+  description = 'Returns local position of a node, relative to its parent.',
+  arguments = {
+    index = {
+      type = 'number',
+      description = 'The index of the node.'
+    },
+    name = {
+      type = 'string',
+      description = 'The name of the node.'
+    }
+  },
+  returns = {
+    x = {
+      type = 'number',
+      description = 'The x coordinate.'
+    },
+    y = {
+      type = 'number',
+      description = 'The y coordinate.'
+    },
+    z = {
+      type = 'number',
+      description = 'The z coordinate.'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'index' },
+      returns = { 'x', 'y', 'z' }
+    },
+    {
+      arguments = { 'name' },
+      returns = { 'x', 'y', 'z' }
+    }
+  },
+  related = {
+    'ModelData:getNodeOrientation',
+    'ModelData:getNodeScale',
+    'ModelData:getNodePose',
+    'ModelData:getNodeTransform'
+  }
+}

+ 44 - 0
api/lovr/data/ModelData/getNodeScale.lua

@@ -0,0 +1,44 @@
+return {
+  summary = 'Get the local scale of a node.',
+  description = 'Returns local scale of a node, relative to its parent.',
+  arguments = {
+    index = {
+      type = 'number',
+      description = 'The index of the node.'
+    },
+    name = {
+      type = 'string',
+      description = 'The name of the node.'
+    }
+  },
+  returns = {
+    sx = {
+      type = 'number',
+      description = 'The x scale.'
+    },
+    sy = {
+      type = 'number',
+      description = 'The y scale.'
+    },
+    sz = {
+      type = 'number',
+      description = 'The z scale.'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'index' },
+      returns = { 'sx', 'sy', 'sz' }
+    },
+    {
+      arguments = { 'name' },
+      returns = { 'sx', 'sy', 'sz' }
+    }
+  },
+  related = {
+    'ModelData:getNodePosition',
+    'ModelData:getNodeOrientation',
+    'ModelData:getNodePose',
+    'ModelData:getNodeTransform'
+  }
+}

+ 37 - 0
api/lovr/data/ModelData/getNodeSkin.lua

@@ -0,0 +1,37 @@
+return {
+  summary = 'Get the index of the skin used by a node.',
+  description = [[
+    Returns the index of the skin used by a node.  Skins are collections of joints used for skeletal
+    animation.  A model can have multiple skins, and each node can use at most one skin to drive the
+    animation of its meshes.
+  ]],
+  arguments = {
+    index = {
+      type = 'number',
+      description = 'The index of the node.'
+    },
+    name = {
+      type = 'string',
+      description = 'The name of the node.'
+    }
+  },
+  returns = {
+    skin = {
+      type = 'number',
+      description = 'The index of the node\'s skin, or nil if the node isn\'t skeletally animated.'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'index' },
+      returns = { 'skin' }
+    },
+    {
+      arguments = { 'name' },
+      returns = { 'skin' }
+    }
+  },
+  related = {
+    'ModelData:getSkinCount'
+  }
+}

+ 74 - 0
api/lovr/data/ModelData/getNodeTransform.lua

@@ -0,0 +1,74 @@
+return {
+  summary = 'Get the local transform of a node.',
+  description = [[
+    Returns local transform (position, orientation, and scale) of a node, relative to its parent.
+  ]],
+  arguments = {
+    index = {
+      type = 'number',
+      description = 'The index of the node.'
+    },
+    name = {
+      type = 'string',
+      description = 'The name of the node.'
+    }
+  },
+  returns = {
+    x = {
+      type = 'number',
+      description = 'The x coordinate.'
+    },
+    y = {
+      type = 'number',
+      description = 'The y coordinate.'
+    },
+    z = {
+      type = 'number',
+      description = 'The z coordinate.'
+    },
+    sx = {
+      type = 'number',
+      description = 'The x scale.'
+    },
+    sy = {
+      type = 'number',
+      description = 'The y scale.'
+    },
+    sz = {
+      type = 'number',
+      description = 'The z scale.'
+    },
+    angle = {
+      type = 'number',
+      description = 'The number of radians the node is rotated around its axis of rotation.'
+    },
+    ax = {
+      type = 'number',
+      description = 'The x component of the axis of rotation.'
+    },
+    ay = {
+      type = 'number',
+      description = 'The y component of the axis of rotation.'
+    },
+    az = {
+      type = 'number',
+      description = 'The z component of the axis of rotation.'
+    }
+  },
+  variants = {
+    {
+      arguments = { 'index' },
+      returns = { 'x', 'y', 'z', 'sx', 'sy', 'sz', 'angle', 'ax', 'ay', 'az' }
+    },
+    {
+      arguments = { 'name' },
+      returns = { 'x', 'y', 'z', 'sx', 'sy', 'sz', 'angle', 'ax', 'ay', 'az' }
+    }
+  },
+  related = {
+    'ModelData:getNodePosition',
+    'ModelData:getNodeOrientation',
+    'ModelData:getNodeScale',
+    'ModelData:getNodePose'
+  }
+}

+ 17 - 0
api/lovr/data/ModelData/getRootNode.lua

@@ -0,0 +1,17 @@
+return {
+  summary = 'Get the index of the root node.',
+  description = 'Returns the index of the model\'s root node.',
+  arguments = {},
+  returns = {
+    {
+      name = 'root',
+      type = 'number',
+      description = 'The index of the root node.'
+    }
+  },
+  related = {
+    'ModelData:getNodeCount',
+    'ModelData:getNodeParent',
+    'Model:getRootNode'
+  }
+}

+ 19 - 0
api/lovr/data/ModelData/getSkinCount.lua

@@ -0,0 +1,19 @@
+return {
+  summary = 'Get the number of skins in the model.',
+  description = [[
+    Returns the number of skins in the model.  A skin is a collection of joints targeted by an
+    animation.
+  ]],
+  arguments = {},
+  returns = {
+    {
+      name = 'count',
+      type = 'number',
+      description = 'The number of skins in the model.'
+    }
+  },
+  notes = 'There is currently a maximum of 256 skins.',
+  related = {
+    'Model:hasJoints'
+  }
+}

+ 23 - 0
api/lovr/data/ModelData/getSkinInverseBindMatrix.lua

@@ -0,0 +1,23 @@
+return {
+  summary = 'Get the inverse bind matrix for a joint in the skin.',
+  description = 'Returns the inverse bind matrix for a joint in the skin.',
+  arguments = {
+    {
+      name = 'skin',
+      type = 'number',
+      description = 'The index of a skin.'
+    },
+    {
+      name = 'joint',
+      type = 'number',
+      description = 'The index of a joint in the skin.'
+    }
+  },
+  returns = {
+    {
+      name = '...',
+      type = 'number',
+      description = 'The 16 components of the 4x4 inverse bind matrix, in column-major order.'
+    }
+  }
+}

+ 18 - 0
api/lovr/data/ModelData/getSkinJoints.lua

@@ -0,0 +1,18 @@
+return {
+  summary = 'Get the joints in a skin.',
+  description = 'Returns a table with the node indices of the joints in a skin.',
+  arguments = {
+    {
+      name = 'skin',
+      type = 'number',
+      description = 'The index of a skin.'
+    }
+  },
+  returns = {
+    {
+      name = 'joints',
+      type = 'table',
+      description = 'The joints in the skin.'
+    }
+  }
+}

+ 21 - 0
api/lovr/data/ModelData/getTriangleCount.lua

@@ -0,0 +1,21 @@
+return {
+  summary = 'Get the total number of triangles in the model.',
+  description = [[
+    Returns the total number of triangles in the model.  This count includes meshes that are
+    attached to multiple nodes, and the count corresponds to the triangles returned by
+    `ModelData:getTriangles`.
+  ]],
+  arguments = {},
+  returns = {
+    {
+      name = 'count',
+      type = 'number',
+      description = 'The total number of triangles in the model.'
+    }
+  },
+  related = {
+    'ModelData:getTriangles',
+    'ModelData:getVertexCount',
+    'Model:getTriangleCount'
+  }
+}

+ 34 - 0
api/lovr/data/ModelData/getTriangles.lua

@@ -0,0 +1,34 @@
+return {
+  summary = 'Get all the triangles in the model.',
+  description = [[
+    Returns the data for all triangles in the model.  There are a few differences between this and
+    the mesh-specific functions like `ModelData:getMeshVertex` and `ModelData:getMeshIndex`:
+
+    - Only vertex positions are returned, not other vertex attributes.
+    - Positions are relative to the origin of the whole model, instead of local to a node.
+    - If a mesh is attached to more than one node, its vertices will be in the table multiple times.
+    - Vertex indices will be relative to the whole triangle list instead of a mesh.
+  ]],
+  arguments = {},
+  returns = {
+    {
+      name = 'vertices',
+      type = 'table',
+      description = [[
+        The triangle vertex positions, returned as a flat (non-nested) table of numbers.  The
+        position of each vertex is given as an x, y, and z coordinate.
+      ]]
+    },
+    {
+      name = 'indices',
+      type = 'table',
+      description = 'The vertex indices.  Every 3 indices describes a triangle.'
+    }
+  },
+  notes = 'After this function is called on a ModelData once, the result is cached.',
+  related = {
+    'ModelData:getTriangleCount',
+    'ModelData:getVertexCount',
+    'Model:getTriangles'
+  }
+}

+ 20 - 0
api/lovr/data/ModelData/getVertexCount.lua

@@ -0,0 +1,20 @@
+return {
+  summary = 'Get the total vertex count of the model.',
+  description = [[
+    Returns the total vertex count of a model.  This count includes meshes that are attached to
+    multiple nodes, and the count corresponds to the vertices returned by `ModelData:getTriangles`.
+  ]],
+  arguments = {},
+  returns = {
+    {
+      name = 'count',
+      type = 'number',
+      description = 'The total number of vertices in the model.'
+    }
+  },
+  related = {
+    'ModelData:getTriangles',
+    'ModelData:getTriangleCount',
+    'Model:getVertexCount'
+  }
+}

+ 20 - 0
api/lovr/data/ModelData/getWidth.lua

@@ -0,0 +1,20 @@
+return {
+  summary = 'Get the width of the model.',
+  description = 'Returns the width of the model, computed from its axis-aligned bounding box.',
+  arguments = {},
+  returns = {
+    {
+      name = 'width',
+      type = 'number',
+      description = 'The width of the model.'
+    }
+  },
+  related = {
+    'ModelData:getHeight',
+    'ModelData:getDepth',
+    'ModelData:getDimensions',
+    'ModelData:getCenter',
+    'ModelData:getBoundingBox',
+    'Model:getWidth'
+  }
+}

+ 18 - 0
api/lovr/data/SmoothMode.lua

@@ -0,0 +1,18 @@
+return {
+  summary = 'Different ways to interpolate between animation keyframes.',
+  description = 'Different ways to interpolate between animation keyframes.',
+  values = {
+    {
+      name = 'step',
+      description = 'The animated property will snap to the nearest keyframe.'
+    },
+    {
+      name = 'linear',
+      description = 'The animated property will linearly interpolate between keyframes.'
+    },
+    {
+      name = 'cubic',
+      description = 'The animated property will follow a smooth curve between nearby keyframes.'
+    }
+  }
+}

+ 218 - 0
api/lovr/data/TextureFormat.lua

@@ -0,0 +1,218 @@
+return {
+  description = [[
+    Different data layouts for pixels in `Image` and `Texture` objects.
+
+    Formats starting with `d` are depth formats, used for depth/stencil render targets.
+
+    Formats starting with `bc` and `astc` are compressed formats.  Compressed formats have better
+    performance since they stay compressed on the CPU and GPU, reducing the amount of memory
+    bandwidth required to look up all the pixels needed for shading.
+
+    Formats without the `f` suffix are unsigned normalized formats, which store values in the range
+    `[0,1]`.  The `f` suffix indicates a floating point format which can store values outside this
+    range, and is used for HDR rendering or storing data in a texture.
+  ]],
+  values = {
+    {
+      name = 'r8',
+      description = 'One 8-bit channel.  1 byte per pixel.'
+    },
+    {
+      name = 'rg8',
+      description = 'Two 8-bit channels.  2 bytes per pixel.'
+    },
+    {
+      name = 'rgba8',
+      description = 'Four 8-bit channels.  4 bytes per pixel.'
+    },
+    {
+      name = 'r16',
+      description = 'One 16-bit channel.  2 bytes per pixel.'
+    },
+    {
+      name = 'rg16',
+      description = 'Two 16-bit channels.  4 bytes per pixel.'
+    },
+    {
+      name = 'rgba16',
+      description = 'Four 16-bit channels.  8 bytes per pixel.'
+    },
+    {
+      name = 'r16f',
+      description = 'One 16-bit floating point channel.  2 bytes per pixel.'
+    },
+    {
+      name = 'rg16f',
+      description = 'Two 16-bit floating point channels.  4 bytes per pixel.'
+    },
+    {
+      name = 'rgba16f',
+      description = 'Four 16-bit floating point channels.  8 bytes per pixel.'
+    },
+    {
+      name = 'r32f',
+      description = 'One 32-bit floating point channel.  4 bytes per pixel.'
+    },
+    {
+      name = 'rg32f',
+      description = 'Two 32-bit floating point channels.  8 bytes per pixel.'
+    },
+    {
+      name = 'rgba32f',
+      description = 'Four 32-bit floating point channels.  16 bytes per pixel.'
+    },
+    {
+      name = 'rgb565',
+      description = 'Packs three channels into 16 bits.  2 bytes per pixel.'
+    },
+    {
+      name = 'rgb5a1',
+      description = 'Packs four channels into 16 bits, with "cutout" alpha.  2 bytes per pixel.'
+    },
+    {
+      name = 'rgb10a2',
+      description = 'Packs four channels into 32 bits.  4 bytes per pixel.'
+    },
+    {
+      name = 'rg11b10f',
+      description = 'Packs three unsigned floating point channels into 32 bits.  4 bytes per pixel.'
+    },
+    {
+      name = 'd16',
+      description = 'One 16-bit depth channel.  2 bytes per pixel.'
+    },
+    {
+      name = 'd24s8',
+      description = 'One 24-bit depth channel and one 8-bit stencil channel.  4 bytes per pixel.'
+    },
+    {
+      name = 'd32f',
+      description = 'One 32-bit floating point depth channel.  4 bytes per pixel.'
+    },
+    {
+      name = 'bc1',
+      description = [[
+        3 channels.  8 bytes per 4x4 block, or 0.5 bytes per pixel.  Good for opaque images.
+      ]]
+    },
+    {
+      name = 'bc2',
+      description = [[
+        Four channels.  16 bytes per 4x4 block or 1 byte per pixel.  Not good for anything, because
+        it only has 16 distinct levels of alpha.
+      ]]
+    },
+    {
+      name = 'bc3',
+      description = [[
+        Four channels.  16 bytes per 4x4 block or 1 byte per pixel.  Good for color images with
+        transparency.
+      ]]
+    },
+    {
+      name = 'bc4u',
+      description = [[
+        One unsigned normalized channel.  8 bytes per 4x4 block or 0.5 bytes per pixel.  Good for
+        grayscale images, like heightmaps.
+      ]]
+    },
+    {
+      name = 'bc4s',
+      description = [[
+        One signed normalized channel.  8 bytes per 4x4 block or 0.5 bytes per pixel.  Similar to
+        bc4u but has a range of -1 to 1.
+      ]]
+    },
+    {
+      name = 'bc5u',
+      description = [[
+        Two unsigned normalized channels.  16 bytes per 4x4 block, or 1 byte per pixel.  Good for
+        normal maps.
+      ]]
+    },
+    {
+      name = 'bc5s',
+      description = [[
+        Two signed normalized channels.  16 bytes per 4x4 block or 1 byte per pixel.  Good for
+        normal maps.
+      ]]
+    },
+    {
+      name = 'bc6uf',
+      description = [[
+        Three unsigned floating point channels.  16 bytes per 4x4 block or 1 byte per pixel.  Good
+        for HDR images.
+      ]]
+    },
+    {
+      name = 'bc6sf',
+      description = [[
+        Three floating point channels.  16 bytes per 4x4 block or 1 byte per pixel.  Good for HDR
+        images.
+      ]]
+    },
+    {
+      name = 'bc7',
+      description = [[
+        Four channels.  16 bytes per 4x4 block or 1 byte per pixel.  High quality.  Good for most
+        color images, including transparency.
+      ]]
+    },
+    {
+      name = 'astc4x4',
+      description = 'Four channels, 16 bytes per 4x4 block or 1 byte per pixel.'
+    },
+    {
+      name = 'astc5x4',
+      description = 'Four channels, 16 bytes per 5x4 block or 0.80 bytes per pixel.'
+    },
+    {
+      name = 'astc5x5',
+      description = 'Four channels, 16 bytes per 5x5 block or 0.64 bytes per pixel.'
+    },
+    {
+      name = 'astc6x5',
+      description = 'Four channels, 16 bytes per 6x5 block or 0.53 bytes per pixel.'
+    },
+    {
+      name = 'astc6x6',
+      description = 'Four channels, 16 bytes per 6x6 block or 0.44 bytes per pixel.'
+    },
+    {
+      name = 'astc8x5',
+      description = 'Four channels, 16 bytes per 8x5 block or 0.40 bytes per pixel.'
+    },
+    {
+      name = 'astc8x6',
+      description = 'Four channels, 16 bytes per 8x6 block or 0.33 bytes per pixel.'
+    },
+    {
+      name = 'astc8x8',
+      description = 'Four channels, 16 bytes per 8x8 block or 0.25 bytes per pixel.'
+    },
+    {
+      name = 'astc10x5',
+      description = 'Four channels, 16 bytes per 10x5 block or 0.32 bytes per pixel.'
+    },
+    {
+      name = 'astc10x6',
+      description = 'Four channels, 16 bytes per 10x6 block or 0.27 bytes per pixel.'
+    },
+    {
+      name = 'astc10x8',
+      description = 'Four channels, 16 bytes per 10x8 block or 0.20 bytes per pixel.'
+    },
+    {
+      name = 'astc10x10',
+      description = 'Four channels, 16 bytes per 10x10 block or 0.16 bytes per pixel.'
+    },
+    {
+      name = 'astc12x10',
+      description = 'Four channels, 16 bytes per 12x10 block or 0.13 bytes per pixel.'
+    },
+    {
+      name = 'astc12x12',
+      description = 'Four channels, 16 bytes per 12x12 block or 0.11 bytes per pixel.'
+    }
+  }
+}

+ 0 - 20
api/lovr/graphics/ArcMode.lua

@@ -1,20 +0,0 @@
-return {
-  summary = 'Different ways arcs can be drawn.',
-  description = 'Different ways arcs can be drawn with `lovr.graphics.arc`.',
-  values = {
-    {
-      name = 'pie',
-      description = [[
-        The arc is drawn with the center of its circle included in the list of points (default).
-      ]]
-    },
-    {
-      name = 'open',
-      description = 'The curve of the arc is drawn as a single line.'
-    },
-    {
-      name = 'closed',
-      description = 'The starting and ending points of the arc\'s curve are connected.'
-    }
-  }
-}

+ 0 - 43
api/lovr/graphics/AttributeType.lua

@@ -1,43 +0,0 @@
-return {
-  summary = 'Different data types for the vertex attributes of a Mesh.',
-  description = [[
-    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.
-  ]],
-  values = {
-    {
-      name = 'byte',
-      description = 'A signed 8 bit number, from -128 to 127.'
-    },
-    {
-      name = 'ubyte',
-      description = 'An unsigned 8 bit number, from 0 to 255.'
-    },
-    {
-      name = 'short',
-      description = 'A signed 16 bit number, from -32768 to 32767.'
-    },
-    {
-      name = 'ushort',
-      description = 'An unsigned 16 bit number, from 0 to 65535.'
-    },
-    {
-      name = 'int',
-      description = 'A signed 32 bit number, from -2147483648 to 2147483647.'
-    },
-    {
-      name = 'uint',
-      description = 'An unsigned 32 bit number, from 0 to 4294967295.'
-    },
-    {
-      name = 'float',
-      description = 'A 32 bit floating-point number (large range, but can start to lose precision).'
-    }
-  },
-  related = {
-    'lovr.graphics.newMesh',
-    'Mesh:getVertexFormat',
-    'Mesh'
-  }
-}

+ 0 - 28
api/lovr/graphics/BlendAlphaMode.lua

@@ -1,28 +0,0 @@
-return {
-  summary = 'Different ways of blending alpha.',
-  description = 'Different ways the alpha channel of pixels affects blending.',
-  values = {
-    {
-      name = 'alphamultiply',
-      description = 'Color channel values are multiplied by the alpha channel during blending.'
-    },
-    {
-      name = 'premultiplied',
-      description = [[
-        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.
-      ]]
-    }
-  },
-  notes = [[
-    The premultiplied mode should be used if pixels being drawn have already been blended, or
-    "pre-multiplied", by the alpha channel.  This happens when rendering a framebuffer that contains
-    pixels with transparent alpha values, since the stored color values have already been faded by
-    alpha and don't need to be faded a second time with the alphamultiply blend mode.
-  ]],
-  related = {
-    'BlendMode',
-    'lovr.graphics.getBlendMode',
-    'lovr.graphics.setBlendMode'
-  }
-}

+ 0 - 50
api/lovr/graphics/BlendMode.lua

@@ -1,50 +0,0 @@
-return {
-  summary = 'Different blend modes.',
-  description = [[
-    Blend modes control how overlapping pixels are blended together, similar to layers in Photoshop.
-  ]],
-  values = {
-    {
-      name = 'alpha',
-      description = 'Normal blending where the alpha value controls how the colors are blended.'
-    },
-    {
-      name = 'add',
-      description = 'The incoming pixel color is added to the destination pixel color.'
-    },
-    {
-      name = 'subtract',
-      description = 'The incoming pixel color is subtracted from the destination pixel color.'
-    },
-    {
-      name = 'multiply',
-      description = [[
-        The color channels from the two pixel values are multiplied together to produce a result.
-      ]]
-    },
-    {
-      name = 'lighten',
-      description = [[
-        The maximum value from each color channel is used, resulting in a lightening effect.
-      ]]
-    },
-    {
-      name = 'darken',
-      description = [[
-        The minimum value from each color channel is used, resulting in a darkening effect.
-      ]]
-    },
-    {
-      name = 'screen',
-      description = [[
-        The opposite of multiply: The pixel values are inverted, multiplied, and inverted again,
-        resulting in a lightening effect.
-      ]]
-    }
-  },
-  related = {
-    'BlendAlphaMode',
-    'lovr.graphics.getBlendMode',
-    'lovr.graphics.setBlendMode'
-  }
-}

+ 0 - 29
api/lovr/graphics/BlockType.lua

@@ -1,29 +0,0 @@
-return {
-  summary = 'Different types of ShaderBlocks.',
-  description = [[
-    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.
-  ]],
-  values = {
-    {
-      name = 'uniform',
-      description = 'A uniform block.'
-    },
-    {
-      name = 'compute',
-      description = 'A compute block.'
-    }
-  },
-  related = {
-    'ShaderBlock',
-    'lovr.graphics.newShaderBlock',
-    'ShaderBlock:getType',
-    'lovr.graphics.getLimits'
-  }
-}

+ 29 - 0
api/lovr/graphics/Buffer/clear.lua

@@ -0,0 +1,29 @@
+return {
+  summary = 'Clear the data in the Buffer.',
+  description = [[
+    Clears some or all of the data in the Buffer to zero.  This is supported for both temporary and
+    permanent Buffers.  Permanent Buffers can also be cleared in a transfer pass using `Pass:clear`.
+  ]],
+  arguments = {
+    {
+      name = 'index',
+      type = 'number',
+      default = '1',
+      description = 'The index of the first item to clear.'
+    },
+    {
+      name = 'count',
+      type = 'number',
+      default = 'nil',
+      description = 'The number of items to clear.  If `nil`, clears as many items as possible.'
+    }
+  },
+  returns = {},
+  notes = [[
+    Clearing a permanent buffer requires the byte offset and byte count of the cleared range to be a
+    multiple of 4.  This will usually be true for most field types.
+  ]],
+  related = {
+    'Pass:clear'
+  }
+}

+ 36 - 0
api/lovr/graphics/Buffer/getFormat.lua

@@ -0,0 +1,36 @@
+return {
+  summary = 'Get the format of the Buffer.',
+  description = [[
+    Returns the format of the Buffer.  This is the list of fields that comprise each item in the
+    buffer.  Each field has a type, byte offset, and vertex attribute location.
+  ]],
+  arguments = {},
+  returns = {
+    {
+      name = 'format',
+      type = 'table',
+      description = 'The format of the Buffer.'
+    }
+  },
+  example = [=[
+    function lovr.load()
+      buffer = lovr.graphics.newBuffer(1, { 'vec3', 'vec3', 'vec2' })
+
+      for i, field in ipairs(buffer:getFormat()) do
+        local type, offset, location = field.type, field.offset, field.location
+        local template = 'Field: %d: Type = %s, Offset = %d, Location = %d'
+        print(template:format(i, type, offset, location))
+      end
+
+      -- prints the following:
+      -- Field 1: Type = f32x3, Offset = 0, Location = 0
+      -- Field 2: Type = f32x3, Offset = 12, Location = 1
+      -- Field 3: Type = f32x2, Offset = 24, Location = 2
+    end
+  ]=],
+  related = {
+    'Buffer:getSize',
+    'Buffer:getLength',
+    'Buffer:getStride'
+  }
+}

+ 16 - 0
api/lovr/graphics/Buffer/getLength.lua

@@ -0,0 +1,16 @@
+return {
+  summary = 'Get the length of the Buffer.',
+  description = 'Returns the length of the Buffer.',
+  arguments = {},
+  returns = {
+    {
+      name = 'length',
+      type = 'number',
+      description = 'The length of the Buffer.'
+    }
+  },
+  related = {
+    'Buffer:getSize',
+    'Buffer:getStride'
+  }
+}

+ 19 - 0
api/lovr/graphics/Buffer/getPointer.lua

@@ -0,0 +1,19 @@
+return {
+  summary = 'Get a raw pointer to the Buffer\'s memory.',
+  description = [[
+    Returns a raw pointer to the Buffer's memory as a lightuserdata, intended for use with the
+    LuaJIT ffi or for passing to C libraries.  This is only available for temporary buffers, and as
+    such the pointer is only valid until `lovr.graphics.submit` is called.
+  ]],
+  arguments = {},
+  returns = {
+    {
+      name = 'pointer',
+      type = 'lightuserdata',
+      description = 'A pointer to the Buffer\'s memory.'
+    }
+  },
+  related = {
+    'Blob:getPointer'
+  }
+}

+ 16 - 0
api/lovr/graphics/Buffer/getSize.lua

@@ -0,0 +1,16 @@
+return {
+  summary = 'Get the size of the Buffer, in bytes.',
+  description = 'Returns the size of the Buffer, in bytes.  This is the same as `length * stride`.',
+  arguments = {},
+  returns = {
+    {
+      name = 'size',
+      type = 'number',
+      description = 'The size of the Buffer, in bytes.'
+    }
+  },
+  related = {
+    'Buffer:getLength',
+    'Buffer:getStride'
+  }
+}

+ 23 - 0
api/lovr/graphics/Buffer/getStride.lua

@@ -0,0 +1,23 @@
+return {
+  summary = 'Get the distance between each item in the Buffer, in bytes.',
+  description = 'Returns the distance between each item in the Buffer, in bytes.',
+  arguments = {},
+  returns = {
+    {
+      name = 'stride',
+      type = 'number',
+      description = 'The stride of the Buffer, in bytes.'
+    }
+  },
+  notes = [[
+    When a Buffer is created, the stride can be set explicitly, otherwise it will be automatically
+    computed based on the fields in the Buffer.
+
+    Strides can not be zero, and can not be smaller than the size of a single item.  To work around
+    this, bind the Buffer as a storage buffer and fetch data from the buffer manually.
+  ]],
+  related = {
+    'Buffer:getSize',
+    'Buffer:getLength'
+  }
+}

+ 39 - 0
api/lovr/graphics/Buffer/init.lua

@@ -0,0 +1,39 @@
+return {
+  summary = 'A block of memory on the GPU.',
+  description = [[
+    A Buffer is a block of GPU memory.  Buffers are similar to Lua tables or arrays: they have a
+    length and store a list of values.  The length of a Buffer and its format (the type of each
+    value) are declared upfront and can't be changed.  Each value of a Buffer consists of one or
+    more fields, and each field has a type.  For example, if a Buffer is used to store vertices,
+    each value might store 3 fields for the position, normal vector, and UV coordinates of a vertex.
+
+    Buffers are commonly used for:
+
+    - Mesh data: Buffers hold the data that define the vertices in a mesh. Buffers also store the
+      vertex indices of a mesh, which define the order the vertices are connected together into
+      triangles. These are often called vertex buffers and index buffers.
+    - Shader data: Buffers can be bound to a Shader, letting the Shader read arbitrary data. For
+      example, Lua code could create a Buffer with the positions and colors of all the lights in a
+      scene, which a Shader can use to do lighting calculations.
+    - Compute: Compute shaders can write data to Buffers.  This GPU-generated data can be used in
+      later rendering work or sent back to Lua.
+    - Indirect: Indirect rendering is an advanced technique where instructions for rendering work
+      are recorded to a Buffer (potentially by a compute shader) and later drawn.
+
+    There are two types of Buffers:
+
+    - **Temporary** buffers are very inexpensive to create, and writing to them from Lua is fast.
+      However, they become invalid at the end of `lovr.draw` (i.e. when `lovr.graphics.submit` is
+      called).  The GPU is slightly slower at accessing data from temporary buffers, and compute
+      shaders can not write to them.  They are designed for storing data that changes every frame.
+    - **Permanent** buffers are more expensive to create, and updating their contents requires a
+      transfer from CPU memory to VRAM.  They act like normal LÖVR objects and don't need to be
+      recreated every frame.  They often have faster performance when used by the GPU, and compute
+      shaders can write to them.  They are great for large pieces of data that are initialized once
+      at load time, or data that is updated infrequently.
+  ]],
+  constructors = {
+    'lovr.graphics.getBuffer',
+    'lovr.graphics.newBuffer'
+  }
+}

+ 15 - 0
api/lovr/graphics/Buffer/isTemporary.lua

@@ -0,0 +1,15 @@
+return {
+  summary = 'Check if the Buffer is temporary.',
+  description = 'Returns whether the Buffer is temporary.',
+  arguments = {},
+  returns = {
+    {
+      name = 'temporary',
+      type = 'boolean',
+      description = 'Whether the Buffer is temporary.'
+    }
+  },
+  related = {
+    'lovr.graphics.getBuffer'
+  }
+}

+ 97 - 0
api/lovr/graphics/Buffer/setData.lua

@@ -0,0 +1,97 @@
+return {
+  summary = 'Change the data in the Buffer.',
+  description = [[
+    Changes data in the Buffer using a table or a Blob.  This is supported for both temporary and
+    permanent buffers.  All passes submitted to the GPU will use the new data.
+
+    It is also possible to change the data in permanent buffers inside of a transfer pass using
+    `Pass:copy`.  Using a transfer pass allows the copy to happen after other passes in the frame.
+  ]],
+  arguments = {
+    data = {
+      type = 'table',
+      description = 'A flat or nested table of items to copy to the Buffer (see notes for format).'
+    },
+    sourceIndex = {
+      type = 'number',
+      default = '1',
+      description = 'The index in the table to copy from.'
+    },
+    destinationIndex = {
+      type = 'number',
+      default = '1',
+      description = 'The index of the first value in the Buffer to update.'
+    },
+    count = {
+      type = 'number',
+      default = 'nil',
+      description = [[
+        The number of values to update.  `nil` will copy as many items as possible, based on the
+        lengths of the source and destination.
+      ]]
+    },
+    blob = {
+      type = 'Blob',
+      description = 'The Blob to copy data from.'
+    },
+    sourceOffset = {
+      type = 'number',
+      default = '0',
+      description = 'A byte offset into the Blob to copy from.'
+    },
+    destinationOffset = {
+      type = 'number',
+      default = '0',
+      description = 'A byte offset in the Buffer to copy to.'
+    },
+    size = {
+      type = 'number',
+      default = 'nil',
+      description = 'The number of bytes to copy.  If nil, copies as many bytes as possible.'
+    }
+  },
+  returns = {},
+  variants = {
+    {
+      arguments = { 'data', 'sourceIndex', 'destinationIndex', 'count' },
+      returns = {}
+    },
+    {
+      arguments = { 'blob', 'sourceOffset', 'destinationOffset', 'size' },
+      returns = {}
+    }
+  },
+  notes = [[
+    When using a table, the table can contain a nested table for each value in the Buffer, or it can
+    be a flat list of field component values.  It is not possible to mix both nested tables and flat
+    values.
+
+    For each item updated, components of each field in the item (according to the Buffer's format)
+    are read from either the nested subtable or the table itself.  A single number can be used to
+    update a field with a scalar type.  Multiple numbers or a `lovr.math` vector can be used to
+    update a field with a vector or mat4 type.  Multiple numbers can be used to update mat2 and mat3
+    fields.  When updating normalized field types, components read from the table will be clamped to
+    the normalized range ([0,1] or [-1,1]).  In the Buffer, each field is written at its byte offset
+    according to the Buffer's format, and subsequent items are separated by the byte stride of the
+    Buffer.  Any missing components for an updated field will be set to zero.
+  ]],
+  example = [[
+    function lovr.load()
+      buffer = lovr.graphics.newBuffer(3, 'floats')
+      buffer:setData({ { 1.0 }, { 2.0 }, { 3.0 } })
+      buffer:setData({ 1.0, 2.0, 3.0 })
+
+      buffer = lovr.graphics.newBuffer(5, { 'vec3', 'vec3', 'vec2' })
+      buffer:setData({ vec3(1, 2, 3), vec3(4, 5, 6), vec2(7, 8) })
+      buffer:setData({ { 1, 2, 3, 4, 5, 6, 7, 8 } })
+      buffer:setData({ 1, 2, 3, 4, 5, 6, 7, 8 })
+      buffer:setData({
+        { x1, y1, z1, nx1, ny1, nz1, u1, v1 },
+        { x2, y2, z2, vec3(nx, ny, nz) }
+      }, 1, 3, 2)
+    end
+  ]],
+  related = {
+    'Pass:copy'
+  }
+}

+ 44 - 0
api/lovr/graphics/BufferLayout.lua

@@ -0,0 +1,44 @@
+return {
+  description = [[
+    The different ways to pack Buffer fields into memory.
+
+    The default is `packed`, which is suitable for vertex buffers and index buffers.  It doesn't add
+    any padding between elements, and so it doesn't waste any space.  However, this layout won't
+    necessarily work for uniform buffers and storage buffers.
+
+    The `std140` layout corresponds to the std140 layout used for uniform buffers in GLSL.  It adds
+    the most padding between fields, and requires the stride to be a multiple of 16.  Example:
+
+    ```
+    layout(std140) uniform ObjectScales { float scales[64]; };
+    ```
+
+    The `std430` layout corresponds to the std430 layout used for storage buffers in GLSL.  It adds
+    some padding between certain types, and may round up the stride.  Example:
+
+    ```
+    layout(std430) buffer TileSizes { vec2 sizes[]; }
+    ```
+  ]],
+  values = {
+    {
+      name = 'packed',
+      description = 'The packed layout, without any padding.'
+    },
+    {
+      name = 'std140',
+      description = 'The std140 layout.'
+    },
+    {
+      name = 'std430',
+      description = 'The std430 layout.'
+    }
+  },
+  related = {
+    'lovr.graphics.newBuffer',
+    'lovr.graphics.getBuffer',
+    'Buffer:getFormat',
+    'Buffer:getStride',
+    'FieldType'
+  }
+}

+ 0 - 24
api/lovr/graphics/BufferUsage.lua

@@ -1,24 +0,0 @@
-return {
-  summary = 'How the buffer data will be updated.',
-  description = [[
-    This acts as a hint to the graphics driver about what kinds of data access should be optimized for.
-  ]],
-  values = {
-    {
-      name = 'static',
-      description = 'A buffer that you intend to create once and never modify.'
-    },
-    {
-      name = 'dynamic',
-      description = 'A buffer which is modified occasionally.'
-    },
-    {
-      name = 'stream',
-      description = 'A buffer which is entirely replaced on the order of every frame.'
-    }
-  },
-  related = {
-    'ShaderBlock',
-    'lovr.graphics.newShaderBlock',
-  }
-}

+ 0 - 19
api/lovr/graphics/Canvas/getDepthTexture.lua

@@ -1,19 +0,0 @@
-return {
-  summary = 'Get the depth buffer used by the Canvas.',
-  description = [[
-    Returns the depth buffer used by the Canvas as a Texture.  If the Canvas was not created with a
-    readable depth buffer (the `depth.readable` flag in `lovr.graphics.newCanvas`), then this
-    function will return `nil`.
-  ]],
-  arguments = {},
-  returns = {
-    {
-      name = 'texture',
-      type = 'Texture',
-      description = 'The depth Texture of the Canvas.'
-    }
-  },
-  related = {
-    'lovr.graphics.newCanvas'
-  }
-}

+ 0 - 22
api/lovr/graphics/Canvas/getDimensions.lua

@@ -1,22 +0,0 @@
-return {
-  summary = 'Get the dimensions of the Canvas.',
-  description = 'Returns the dimensions of the Canvas, its Textures, and its depth buffer.',
-  arguments = {},
-  returns = {
-    {
-      name = 'width',
-      type = 'number',
-      description = 'The width of the Canvas, in pixels.'
-    },
-    {
-      name = 'height',
-      type = 'number',
-      description = 'The height of the Canvas, in pixels.'
-    }
-  },
-  notes = 'The dimensions of a Canvas can not be changed after it is created.',
-  related = {
-    'Canvas:getWidth',
-    'Canvas:getHeight'
-  }
-}

+ 0 - 17
api/lovr/graphics/Canvas/getHeight.lua

@@ -1,17 +0,0 @@
-return {
-  summary = 'Get the height of the Canvas.',
-  description = 'Returns the height of the Canvas, its Textures, and its depth buffer.',
-  arguments = {},
-  returns = {
-    {
-      name = 'height',
-      type = 'number',
-      description = 'The height of the Canvas, in pixels.'
-    }
-  },
-  notes = 'The height of a Canvas can not be changed after it is created.',
-  related = {
-    'Canvas:getWidth',
-    'Canvas:getDimensions'
-  }
-}

+ 0 - 21
api/lovr/graphics/Canvas/getMSAA.lua

@@ -1,21 +0,0 @@
-return {
-  summary = 'Get the number of MSAA samples used by the Canvas.',
-  description = [[
-    Returns the number of multisample antialiasing samples to use when rendering to the Canvas.
-    Increasing this number will make the contents of the Canvas appear more smooth at the cost of
-    performance.  It is common to use powers of 2 for this value.
-  ]],
-  arguments = {},
-  returns = {
-    {
-      name = 'samples',
-      type = 'number',
-      description = 'The number of MSAA samples.'
-    }
-  },
-  notes = 'All textures attached to the Canvas must be created with this MSAA value.',
-  related = {
-    'lovr.graphics.newCanvas',
-    'lovr.graphics.newTexture'
-  }
-}

+ 0 - 13
api/lovr/graphics/Canvas/getTexture.lua

@@ -1,13 +0,0 @@
-return {
-  summary = 'Get the Textures attached to the Canvas.',
-  description = 'Returns the set of Textures currently attached to the Canvas.',
-  arguments = {},
-  returns = {
-    {
-      name = '...',
-      type = 'Texture',
-      description = 'One or more Textures attached to the Canvas.'
-    }
-  },
-  notes = 'Up to 4 Textures can be attached at once.'
-}

+ 0 - 17
api/lovr/graphics/Canvas/getWidth.lua

@@ -1,17 +0,0 @@
-return {
-  summary = 'Get the width of the Canvas.',
-  description = 'Returns the width of the Canvas, its Textures, and its depth buffer.',
-  arguments = {},
-  returns = {
-    {
-      name = 'width',
-      type = 'number',
-      description = 'The width of the Canvas, in pixels.'
-    }
-  },
-  notes = 'The width of a Canvas can not be changed after it is created.',
-  related = {
-    'Canvas:getHeight',
-    'Canvas:getDimensions'
-  }
-}

+ 0 - 70
api/lovr/graphics/Canvas/init.lua

@@ -1,70 +0,0 @@
-return {
-  summary = 'An offscreen render target.',
-  description = [[
-    A Canvas is also known as a framebuffer or render-to-texture.  It allows you to render to a
-    texture instead of directly to the screen.  This lets you postprocess or transform the results
-    later before finally rendering them to the screen.
-
-    After creating a Canvas, you can attach Textures to it using `Canvas:setTexture`.
-  ]],
-  constructors = {
-    'lovr.graphics.newCanvas'
-  },
-  notes = [[
-    Up to four textures can be attached to a Canvas and anything rendered to the Canvas will be
-    broadcast to all attached Textures.  If you want to do render different things to different
-    textures, use the `multicanvas` shader flag when creating your shader and implement the `void
-    colors` function instead of the usual `vec4 color` function.  You can then assign different
-    output colors to `lovrCanvas[0]`, `lovrCanvas[1]`, etc. instead of returning a single color.
-    Each color written to the array will end up in the corresponding texture attached to the Canvas.
-  ]],
-  example = {
-    description = 'Apply a postprocessing effect (wave) using a Canvas and a fragment shader.',
-    code = [=[
-      function lovr.load()
-        lovr.graphics.setBackgroundColor(.1, .1, .1)
-        canvas = lovr.graphics.newCanvas(lovr.headset.getDisplayDimensions())
-
-        wave = lovr.graphics.newShader([[
-          vec4 position(mat4 projection, mat4 transform, vec4 vertex) {
-            return projection * transform * vertex;
-          }
-        ]], [[
-          uniform float time;
-          vec4 color(vec4 gcolor, sampler2D image, vec2 uv) {
-            uv.x += sin(uv.y * 10 + time * 4) * .01;
-            uv.y += cos(uv.x * 10 + time * 4) * .01;
-            return lovrGraphicsColor * lovrDiffuseColor * lovrVertexColor * texture(lovrDiffuseTexture, uv);
-          }
-        ]])
-      end
-
-      function lovr.update(dt)
-        wave:send('time', lovr.timer.getTime())
-      end
-
-      function lovr.draw()
-        -- Render the scene to the canvas instead of the headset.
-        canvas:renderTo(function()
-          lovr.graphics.clear()
-          local size = 5
-          for i = 1, size do
-            for j = 1, size do
-              for k = 1, size do
-                lovr.graphics.setColor(i / size, j / size, k / size)
-                local x, y, z = i - size / 2, j - size / 2, k - size / 2
-                lovr.graphics.cube('fill', x, y, z, .5)
-              end
-            end
-          end
-        end)
-
-        -- Render the canvas to the headset using a shader.
-        lovr.graphics.setColor(1, 1, 1)
-        lovr.graphics.setShader(wave)
-        lovr.graphics.fill(canvas:getTexture())
-        lovr.graphics.setShader()
-      end
-    ]=]
-  }
-}

+ 0 - 20
api/lovr/graphics/Canvas/isStereo.lua

@@ -1,20 +0,0 @@
-return {
-  summary = 'Check if the Canvas is stereo.',
-  description = [[
-    Returns whether the Canvas was created with the `stereo` flag.  Drawing something to a stereo
-    Canvas will draw it to two viewports in the left and right half of the Canvas, using transform
-    information from two different eyes.
-  ]],
-  arguments = {},
-  returns = {
-    {
-      name = 'stereo',
-      type = 'boolean',
-      description = 'Whether the Canvas is stereo.'
-    }
-  },
-  related = {
-    'lovr.graphics.newCanvas',
-    'lovr.graphics.fill'
-  }
-}

+ 0 - 28
api/lovr/graphics/Canvas/newImage.lua

@@ -1,28 +0,0 @@
-return {
-  summary = 'Create a new Image from a Canvas texture.',
-  description = [[
-    Returns a new Image containing the contents of a Texture attached to the Canvas.
-  ]],
-  arguments = {
-    {
-      name = 'index',
-      type = 'number',
-      default = '1',
-      description = 'The index of the Texture to read from.'
-    }
-  },
-  returns = {
-    {
-      name = 'image',
-      type = 'Image',
-      description = 'The new Image.'
-    }
-  },
-  notes = [[
-    The Image will have the same pixel format as the Texture that is read from.
-  ]],
-  related = {
-    'lovr.data.newImage',
-    'Image'
-  }
-}

+ 0 - 36
api/lovr/graphics/Canvas/renderTo.lua

@@ -1,36 +0,0 @@
-return {
-  summary = 'Render to the Canvas using a function.',
-  description = [[
-    Renders to the Canvas using a function.  All graphics functions inside the callback will affect
-    the Canvas contents instead of directly rendering to the headset.  This can be used in
-    `lovr.update`.
-  ]],
-  arguments = {
-    {
-      name = 'callback',
-      type = 'function',
-      arguments = {
-        {
-          name = '...',
-          type = '*'
-        }
-      },
-      returns = {},
-      description = 'The function to use to render to the Canvas.'
-    },
-    {
-      name = '...',
-      type = '*',
-      description = 'Additional arguments to pass to the callback.'
-    }
-  },
-  returns = {},
-  notes = [[
-    Make sure you clear the contents of the canvas before rendering by using `lovr.graphics.clear`.
-    Otherwise there might be data in the canvas left over from a previous frame.
-
-    Also note that the transform stack is not modified by this function.  If you plan on modifying
-    the transform stack inside your callback it may be a good idea to use `lovr.graphics.push` and
-    `lovr.graphics.pop` so you can revert to the previous transform afterwards.
-  ]]
-}

+ 0 - 36
api/lovr/graphics/Canvas/setTexture.lua

@@ -1,36 +0,0 @@
-return {
-  summary = 'Attach one or more Textures to the Canvas.',
-  description = [[
-    Attaches one or more Textures to the Canvas.  When rendering to the Canvas, everything will be
-    drawn to all attached Textures.  You can attach different layers of an array, cubemap, or volume
-    texture, and also attach different mipmap levels of Textures.
-  ]],
-  arguments = {
-    {
-      name = '...',
-      type = '*',
-      description = 'One or more Textures to attach to the Canvas.'
-    }
-  },
-  returns = {},
-  notes = [[
-    There are some restrictions on how textures can be attached:
-
-    - Up to 4 textures can be attached at once.
-    - Textures must have the same dimensions and multisample settings as the Canvas.
-
-    To specify layers and mipmaps to attach, specify them after the Texture.  You can also
-    optionally wrap them in a table.
-  ]],
-  example = {
-    description = 'Various ways to attach textures to a Canvas.',
-    code = [[
-      canvas:setTexture(textureA)
-      canvas:setTexture(textureA, textureB) -- Attach two textures
-      canvas:setTexture(textureA, layer, mipmap) -- Attach a specific layer and mipmap
-      canvas:setTexture(textureA, layer, textureB, layer) -- Attach specific layers
-      canvas:setTexture({ textureA, layer, mipmap }, textureB, { textureC, layer }) -- Tables
-      canvas:setTexture({ { textureA, layer, mipmap }, textureB, { textureC, layer } })
-    ]]
-  }
-}

+ 0 - 48
api/lovr/graphics/CompareMode.lua

@@ -1,48 +0,0 @@
-return {
-  summary = 'Different depth test modes.',
-  description = [[
-    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.
-  ]],
-  values = {
-    {
-      name = 'equal',
-      description = 'The depth test passes when the depth values are equal.',
-    },
-    {
-      name = 'notequal',
-      description = 'The depth test passes when the depth values are not equal.',
-    },
-    {
-      name = 'less',
-      description = 'The depth test passes when the new depth value is less than the existing one.',
-    },
-    {
-      name = 'lequal',
-      description = [[
-        The depth test passes when the new depth value is less than or equal to the existing one.
-      ]],
-    },
-    {
-      name = 'gequal',
-      description = [[
-        The depth test passes when the new depth value is greater than or equal to the existing one.
-      ]],
-    },
-    {
-      name = 'greater',
-      description = [[
-        The depth test passes when the new depth value is greater than the existing one.
-      ]]
-    }
-  },
-  related = {
-    'lovr.graphics.getDepthTest',
-    'lovr.graphics.setDepthTest',
-    'lovr.graphics.getStencilTest',
-    'lovr.graphics.setStencilTest'
-  }
-}

+ 0 - 16
api/lovr/graphics/CoordinateSpace.lua

@@ -1,16 +0,0 @@
-return {
-  description = 'Different coordinate spaces for nodes in a Model.',
-  values = {
-    {
-      name = 'local',
-      description = 'The coordinate space relative to the node\'s parent.'
-    },
-    {
-      name = 'global',
-      description = 'The coordinate space relative to the root node of the Model.'
-    }
-  },
-  related = {
-    'Model:pose'
-  }
-}

+ 0 - 38
api/lovr/graphics/DefaultShader.lua

@@ -1,38 +0,0 @@
-return {
-  summary = 'The set of builtin shaders.',
-  description = [[
-    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.
-  ]],
-  values = {
-    {
-      name = 'unlit',
-      description = 'A simple shader without lighting, using only colors and a diffuse texture.'
-    },
-    {
-      name = 'standard',
-      description = 'A physically-based rendering (PBR) shader, using advanced material properties.'
-    },
-    {
-      name = 'cube',
-      description = 'A shader that renders a cubemap texture.'
-    },
-    {
-      name = 'pano',
-      description = 'A shader that renders a 2D equirectangular texture with spherical coordinates.'
-    },
-    {
-      name = 'font',
-      description = 'A shader that renders font glyphs.'
-    },
-    {
-      name = 'fill',
-      description = [[
-        A shader that passes its vertex coordinates unmodified to the fragment shader, used to
-        render view-independent fixed geometry like fullscreen quads.
-      ]]
-    }
-  }
-}

+ 0 - 49
api/lovr/graphics/DrawMode.lua

@@ -1,49 +0,0 @@
-return {
-  summary = 'Different ways Mesh objects can be drawn.',
-  description = [[
-    Meshes are lists of arbitrary vertices.  These vertices can be connected in different ways,
-    leading to different shapes like lines and triangles.
-  ]],
-  values = {
-    {
-      name = 'points',
-      description = 'Draw each vertex as a single point.'
-    },
-    {
-      name = 'lines',
-      description = [[
-        The vertices represent a list of line segments. Each pair of vertices will have a line drawn
-        between them.
-      ]]
-    },
-    {
-      name = 'linestrip',
-      description = [[
-        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.
-      ]]
-    },
-    {
-      name = 'lineloop',
-      description = 'Similar to linestrip, except the last vertex is connected back to the first.'
-    },
-    {
-      name = 'strip',
-      description = [[
-        The first three vertices define a triangle.  Each vertex after that creates a triangle using
-        the new vertex and last two vertices.
-      ]]
-    },
-    {
-      name = 'triangles',
-      description = 'Each set of three vertices represents a discrete triangle.'
-    },
-    {
-      name = 'fan',
-      description = [[
-        Draws a set of triangles.  Each one shares the first vertex as a common point, leading to a
-        fan-like shape.
-      ]]
-    }
-  }
-}

+ 0 - 16
api/lovr/graphics/DrawStyle.lua

@@ -1,16 +0,0 @@
-return {
-  summary = 'Different ways graphics primitives can be drawn.',
-  description = [[
-    Most graphics primitives can be drawn in one of two modes: a filled mode and a wireframe mode.
-  ]],
-  values = {
-    {
-      name = 'fill',
-      description = 'The shape is drawn as a filled object.'
-    },
-    {
-      name = 'line',
-      description = 'The shape is drawn as a wireframe object.'
-    }
-  }
-}

+ 205 - 0
api/lovr/graphics/FieldType.lua

@@ -0,0 +1,205 @@
+return {
+  description = [[
+    Different types for `Buffer` fields.  These are scalar, vector, or matrix types, usually packed
+    into small amounts of space to reduce the amount of memory they occupy.
+
+    The names are encoded as follows:
+
+    - The data type:
+      - `i` for signed integer
+      - `u` for unsigned integer
+      - `sn` for signed normalized (-1 to 1)
+      - `un` for unsigned normalized (0 to 1)
+      - `f` for floating point
+    - The bit depth of each component
+    - The letter `x` followed by the component count (for vectors)
+  ]],
+  values = {
+    {
+      name = 'i8x4',
+      description = 'Four 8-bit signed integers.'
+    },
+    {
+      name = 'u8x4',
+      description = 'Four 8-bit unsigned integers.'
+    },
+    {
+      name = 'sn8x4',
+      description = 'Four 8-bit signed normalized values.'
+    },
+    {
+      name = 'un8x4',
+      description = 'Four 8-bit unsigned normalized values (aka `color`).'
+    },
+    {
+      name = 'un10x3',
+      description = 'Three 10-bit unsigned normalized values, and 2 padding bits (aka `normal`).'
+    },
+    {
+      name = 'i16',
+      description = 'One 16-bit signed integer.'
+    },
+    {
+      name = 'i16x2',
+      description = 'Two 16-bit signed integers.'
+    },
+    {
+      name = 'i16x4',
+      description = 'Four 16-bit signed integers.'
+    },
+    {
+      name = 'u16',
+      description = 'One 16-bit unsigned integer.'
+    },
+    {
+      name = 'u16x2',
+      description = 'Two 16-bit unsigned integers.'
+    },
+    {
+      name = 'u16x4',
+      description = 'Four 16-bit unsigned integers.'
+    },
+    {
+      name = 'sn16x2',
+      description = 'Two 16-bit signed normalized values.'
+    },
+    {
+      name = 'sn16x4',
+      description = 'Four 16-bit signed normalized values.'
+    },
+    {
+      name = 'un16x2',
+      description = 'Two 16-bit unsigned normalized values.'
+    },
+    {
+      name = 'un16x4',
+      description = 'Four 16-bit unsigned normalized values.'
+    },
+    {
+      name = 'i32',
+      description = 'One 32-bit signed integer (aka `int`).'
+    },
+    {
+      name = 'i32x2',
+      description = 'Two 32-bit signed integers.'
+    },
+    {
+      name = 'i32x2',
+      description = 'Two 32-bit signed integers.'
+    },
+    {
+      name = 'i32x3',
+      description = 'Three 32-bit signed integers.'
+    },
+    {
+      name = 'i32x4',
+      description = 'Four 32-bit signed integers.'
+    },
+    {
+      name = 'u32',
+      description = 'One 32-bit unsigned integer (aka `uint`).'
+    },
+    {
+      name = 'u32x2',
+      description = 'Two 32-bit unsigned integers.'
+    },
+    {
+      name = 'u32x3',
+      description = 'Three 32-bit unsigned integers.'
+    },
+    {
+      name = 'u32x4',
+      description = 'Four 32-bit unsigned integers.'
+    },
+    {
+      name = 'f16x2',
+      description = 'Two 16-bit floating point numbers.'
+    },
+    {
+      name = 'f16x4',
+      description = 'Four 16-bit floating point numbers.'
+    },
+    {
+      name = 'f32',
+      description = 'One 32-bit floating point number (aka `float`).'
+    },
+    {
+      name = 'f32x2',
+      description = 'Two 32-bit floating point numbers (aka `vec2`).'
+    },
+    {
+      name = 'f32x3',
+      description = 'Three 32-bit floating point numbers (aka `vec3`).'
+    },
+    {
+      name = 'f32x4',
+      description = 'Four 32-bit floating point numbers (aka `vec4`).'
+    },
+    {
+      name = 'mat2',
+      description = 'A 2x2 matrix containing four 32-bit floats.'
+    },
+    {
+      name = 'mat3',
+      description = 'A 3x3 matrix containing nine 32-bit floats.'
+    },
+    {
+      name = 'mat4',
+      description = 'A 4x4 matrix containing sixteen 32-bit floats.'
+    },
+  },
+  notes = [[
+    In addition to these values, the following aliases can be used:
+
+    <table>
+      <thead>
+        <tr>
+          <td>Alias</td>
+          <td>Maps to</td>
+        </tr>
+      </thead>
+      <tbody>
+        <tr>
+          <td><code>vec2</code></td>
+          <td><code>f32x2</code></td>
+        </tr>
+        <tr>
+          <td><code>vec3</code></td>
+          <td><code>f32x3</code></td>
+        </tr>
+        <tr>
+          <td><code>vec4</code></td>
+          <td><code>f32x4</code></td>
+        </tr>
+        <tr>
+          <td><code>int</code></td>
+          <td><code>i32</code></td>
+        </tr>
+        <tr>
+          <td><code>uint</code></td>
+          <td><code>u32</code></td>
+        </tr>
+        <tr>
+          <td><code>float</code></td>
+          <td><code>f32</code></td>
+        </tr>
+        <tr>
+          <td><code>color</code></td>
+          <td><code>un8x4</code></td>
+        </tr>
+      </tbody>
+    </table>
+
+    Additionally, the following convenience rules apply:
+
+    - Field types can end in an `s`, which will be stripped off.
+    - Field types can end in `x1`, which will be stripped off.
+
+    So you can write, e.g. `lovr.graphics.newBuffer(4, 'floats')`, which is cute!
+  ]],
+  related = {
+    'lovr.graphics.newBuffer',
+    'lovr.graphics.getBuffer',
+    'Buffer:getFormat'
+  }
+}

+ 0 - 28
api/lovr/graphics/FilterMode.lua

@@ -1,28 +0,0 @@
-return {
-  summary = 'How textures are sampled.',
-  description = [[
-    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.
-  ]],
-  values = {
-    {
-      name = 'nearest',
-      description = 'Fast nearest-neighbor sampling.  Leads to a pixelated style.'
-    },
-    {
-      name = 'bilinear',
-      description = 'Smooth pixel sampling.'
-    },
-    {
-      name = 'trilinear',
-      description = 'Smooth pixel sampling, with smooth sampling across mipmap levels.'
-    }
-  },
-  related = {
-    'Texture:getFilter',
-    'Texture:setFilter',
-    'lovr.graphics.getDefaultFilter',
-    'lovr.graphics.setDefaultFilter',
-    'WrapMode'
-  }
-}

+ 5 - 6
api/lovr/graphics/Font/getAscent.lua

@@ -1,19 +1,18 @@
 return {
   summary = 'Get the ascent of the Font.',
-  description = [[
-    Returns the maximum distance that any glyph will extend above the Font's baseline.  Units are
-    generally in meters, see `Font:getPixelDensity`.
-  ]],
+  description = 'TODO',
   arguments = {},
   returns = {
     {
       name = 'ascent',
       type = 'number',
-      description = 'The ascent of the Font.'
+      description = 'TODO'
     }
   },
   related = {
     'Font:getDescent',
-    'Rasterizer:getAscent'
+    'Font:getHeight',
+    'Font:getKerning',
+    'Font:getWidth'
   }
 }

+ 0 - 15
api/lovr/graphics/Font/getBaseline.lua

@@ -1,15 +0,0 @@
-return {
-  summary = 'Get the baseline of the Font.',
-  description = [[
-    Returns the baseline of the Font.  This is where the characters "rest on", relative to the y
-    coordinate of the drawn text.  Units are generally in meters, see `Font:setPixelDensity`.
-  ]],
-  arguments = {},
-  returns = {
-    {
-      name = 'baseline',
-      type = 'number',
-      description = 'The baseline of the Font.'
-    }
-  }
-}

+ 8 - 6
api/lovr/graphics/Font/getDescent.lua

@@ -1,16 +1,18 @@
 return {
   summary = 'Get the descent of the Font.',
-  description = [[
-    Returns the maximum distance that any glyph will extend below the Font's baseline.  Units are
-    generally in meters, see `Font:getPixelDensity` for more information.  Note that due to the
-    coordinate system for fonts, this is a negative value.
-  ]],
+  description = 'TODO',
   arguments = {},
   returns = {
     {
       name = 'descent',
       type = 'number',
-      description = 'The descent of the Font.'
+      description = 'TODO'
     }
+  },
+  related = {
+    'Font:getAscent',
+    'Font:getHeight',
+    'Font:getKerning',
+    'Font:getWidth'
   }
 }

+ 8 - 6
api/lovr/graphics/Font/getHeight.lua

@@ -1,17 +1,19 @@
 return {
-  summary = 'Get the height of a line of text.',
-  description = [[
-    Returns the height of a line of text.  Units are in meters, see `Font:setPixelDensity`.
-  ]],
+  summary = 'Get the height of the Font.',
+  description = 'TODO',
   arguments = {},
   returns = {
     {
       name = 'height',
       type = 'number',
-      description = 'The height of a rendered line of text.'
+      description = 'TODO'
     }
   },
   related = {
-    'Rasterizer:getHeight'
+    'Font:getAscent',
+    'Font:getDescent',
+    'Font:getKerning',
+    'Font:getWidth',
+    'Font:getLines'
   }
 }

+ 29 - 0
api/lovr/graphics/Font/getKerning.lua

@@ -0,0 +1,29 @@
+return {
+  summary = 'Get the kerning of the Font.',
+  description = 'TODO',
+  arguments = {
+    {
+      name = 'first',
+      type = 'Codepoint',
+      description = 'TODO'
+    },
+    {
+      name = 'second',
+      type = 'Codepoint',
+      description = 'TODO'
+    }
+  },
+  returns = {
+    {
+      name = 'kerning',
+      type = 'number',
+      description = 'TODO'
+    }
+  },
+  related = {
+    'Font:getAscent',
+    'Font:getDescent',
+    'Font:getHeight',
+    'Font:getWidth'
+  }
+}

+ 0 - 16
api/lovr/graphics/Font/getLineHeight.lua

@@ -1,16 +0,0 @@
-return {
-  summary = 'Get the line height of the Font.',
-  description = 'Returns the current line height multiplier of the Font.  The default is 1.0.',
-  arguments = {},
-  returns = {
-    {
-      name = 'lineHeight',
-      type = 'number',
-      description = 'The line height.'
-    }
-  },
-  related = {
-    'Font:getHeight',
-    'Rasterizer:getLineHeight'
-  }
-}

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików