errhand.lua 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. return {
  2. tag = 'callbacks',
  3. summary = 'Called when an error occurs.',
  4. description = [[
  5. The `lovr.errhand` callback is run whenever an error occurs. It receives a parameter containing
  6. the error message. It should return a handler function that will run in a loop to render the
  7. error screen.
  8. This handler function is of the same type as the one returned by `lovr.run` and has the same
  9. requirements (such as pumping events). If an error occurs while this handler is running, the
  10. program will terminate immediately -- `lovr.errhand` will not be given a second chance. Errors
  11. which occur in the error handler or in the handler it returns may not be cleanly reported, so be
  12. careful.
  13. A default error handler is supplied that renders the error message as text to the headset and
  14. to the window.
  15. ]],
  16. arguments = {
  17. {
  18. name = 'message',
  19. type = 'string',
  20. description = 'The error message.'
  21. }
  22. },
  23. returns = {
  24. {
  25. name = 'handler',
  26. type = 'function',
  27. arguments = {},
  28. returns = {
  29. {
  30. name = 'result',
  31. type = '*'
  32. }
  33. },
  34. description = [[
  35. The error handler function. It should return nil to continue running, "restart" to restart
  36. the app, or a number representing an exit status.
  37. ]]
  38. }
  39. },
  40. example = {
  41. description = 'The default error handler.',
  42. code = [[
  43. function lovr.errhand(message)
  44. local function formatTraceback(s)
  45. return s:gsub('\n[^\n]+$', ''):gsub('\t', ''):gsub('stack traceback:', '\nStack:\n')
  46. end
  47. message = 'Error:\n\n' .. tostring(message) .. formatTraceback(debug.traceback('', 4))
  48. print(message)
  49. if not lovr.graphics or not lovr.graphics.isInitialized() then
  50. return function() return 1 end
  51. end
  52. if lovr.audio then lovr.audio.stop() end
  53. if not lovr.headset or lovr.headset.getPassthrough() == 'opaque' then
  54. lovr.graphics.setBackgroundColor(.11, .10, .14)
  55. else
  56. lovr.graphics.setBackgroundColor(0, 0, 0, 0)
  57. end
  58. local font = lovr.graphics.getDefaultFont()
  59. return function()
  60. lovr.system.pollEvents()
  61. for name, a in lovr.event.poll() do
  62. if name == 'quit' then return a or 1
  63. elseif name == 'restart' then return 'restart', lovr.restart and lovr.restart()
  64. elseif name == 'keypressed' and a == 'f5' then lovr.event.restart()
  65. elseif name == 'keypressed' and a == 'escape' then lovr.event.quit() end
  66. end
  67. if lovr.headset and lovr.headset.getDriver() ~= 'desktop' then
  68. lovr.headset.update()
  69. local pass = lovr.headset.getPass()
  70. if pass then
  71. font:setPixelDensity()
  72. local scale = .35
  73. local font = lovr.graphics.getDefaultFont()
  74. local wrap = .7 * font:getPixelDensity()
  75. local lines = font:getLines(message, wrap)
  76. local width = math.min(font:getWidth(message), wrap) * scale
  77. local height = .8 + #lines * font:getHeight() * scale
  78. local x = -width / 2
  79. local y = math.min(height / 2, 10)
  80. local z = -10
  81. pass:setColor(.95, .95, .95)
  82. pass:text(message, x, y, z, scale, 0, 0, 0, 0, wrap, 'left', 'top')
  83. lovr.graphics.submit(pass)
  84. lovr.headset.submit()
  85. end
  86. end
  87. if lovr.system.isWindowOpen() then
  88. local pass = lovr.graphics.getWindowPass()
  89. if pass then
  90. local w, h = lovr.system.getWindowDimensions()
  91. pass:setProjection(1, lovr.math.mat4():orthographic(0, w, 0, h, -1, 1))
  92. font:setPixelDensity(1)
  93. local scale = .6
  94. local wrap = w * .8 / scale
  95. local width = math.min(font:getWidth(message), wrap) * scale
  96. local x = w / 2 - width / 2
  97. pass:setColor(.95, .95, .95)
  98. pass:text(message, x, h / 2, 0, scale, 0, 0, 0, 0, wrap, 'left', 'middle')
  99. lovr.graphics.submit(pass)
  100. lovr.graphics.present()
  101. end
  102. end
  103. lovr.math.drain()
  104. end
  105. end
  106. ]]
  107. },
  108. related = {
  109. 'lovr.quit'
  110. }
  111. }