Procházet zdrojové kódy

New and updated manuals:
- Hot reloading
- Profiling
- Debugging
- Lua modules
- ZeroBrane debugging

Also added support for -- [1] style callouts in code snippets and temp fix for rewriting url:s in srcset. The rewriting does not work with multiple srcset entries so it needs to be properly fixed.

Mikael Säker před 7 roky
rodič
revize
ddbf492d38
72 změnil soubory, kde provedl 621 přidání a 670 odebrání
  1. 12 4
      docs/en/en.json
  2. 84 139
      docs/en/manuals/debugging.md
  3. 17 1
      docs/en/manuals/glossary.md
  4. 122 0
      docs/en/manuals/hot-reload.md
  5. binární
      docs/en/manuals/images/debugging/add_breakpoint.png
  6. binární
      docs/en/manuals/images/debugging/[email protected]
  7. binární
      docs/en/manuals/images/debugging/break.png
  8. binární
      docs/en/manuals/images/debugging/[email protected]
  9. binární
      docs/en/manuals/images/debugging/callstack.png
  10. binární
      docs/en/manuals/images/debugging/[email protected]
  11. binární
      docs/en/manuals/images/debugging/console.png
  12. binární
      docs/en/manuals/images/debugging/[email protected]
  13. binární
      docs/en/manuals/images/debugging/debugging_hot_reload.png
  14. binární
      docs/en/manuals/images/debugging/debugging_profiling.png
  15. binární
      docs/en/manuals/images/debugging/download_container.png
  16. binární
      docs/en/manuals/images/debugging/[email protected]
  17. binární
      docs/en/manuals/images/debugging/overview.png
  18. binární
      docs/en/manuals/images/debugging/[email protected]
  19. 1 0
      docs/en/manuals/images/debugging/pause.svg
  20. 1 0
      docs/en/manuals/images/debugging/play.svg
  21. binární
      docs/en/manuals/images/debugging/script.png
  22. binární
      docs/en/manuals/images/debugging/[email protected]
  23. binární
      docs/en/manuals/images/debugging/showinfind.png
  24. binární
      docs/en/manuals/images/debugging/showinwin.png
  25. binární
      docs/en/manuals/images/debugging/step.png
  26. binární
      docs/en/manuals/images/debugging/[email protected]
  27. 1 0
      docs/en/manuals/images/debugging/step_in.svg
  28. binární
      docs/en/manuals/images/debugging/step_into.png
  29. binární
      docs/en/manuals/images/debugging/[email protected]
  30. 1 0
      docs/en/manuals/images/debugging/step_out.svg
  31. 1 0
      docs/en/manuals/images/debugging/step_over.svg
  32. 1 0
      docs/en/manuals/images/debugging/stop.svg
  33. binární
      docs/en/manuals/images/debugging/variables.png
  34. binární
      docs/en/manuals/images/debugging/[email protected]
  35. binární
      docs/en/manuals/images/hot-reload/gui-reloaded.png
  36. binární
      docs/en/manuals/images/hot-reload/[email protected]
  37. binární
      docs/en/manuals/images/hot-reload/gui.png
  38. binární
      docs/en/manuals/images/hot-reload/[email protected]
  39. binární
      docs/en/manuals/images/hot-reload/menu.png
  40. binární
      docs/en/manuals/images/hot-reload/[email protected]
  41. binární
      docs/en/manuals/images/hot-reload/target.png
  42. binární
      docs/en/manuals/images/hot-reload/[email protected]
  43. binární
      docs/en/manuals/images/modules/modules_new.png
  44. binární
      docs/en/manuals/images/modules/modules_new_name.png
  45. binární
      docs/en/manuals/images/modules/new_name.png
  46. binární
      docs/en/manuals/images/modules/[email protected]
  47. binární
      docs/en/manuals/images/profiling/android_profiler.png
  48. binární
      docs/en/manuals/images/profiling/build_report.png
  49. binární
      docs/en/manuals/images/profiling/[email protected]
  50. binární
      docs/en/manuals/images/profiling/build_report_html.png
  51. binární
      docs/en/manuals/images/profiling/[email protected]
  52. binární
      docs/en/manuals/images/profiling/gapid.png
  53. binární
      docs/en/manuals/images/profiling/instruments.png
  54. binární
      docs/en/manuals/images/profiling/[email protected]
  55. binární
      docs/en/manuals/images/profiling/opengl.png
  56. binární
      docs/en/manuals/images/profiling/[email protected]
  57. binární
      docs/en/manuals/images/profiling/visual_profiler.png
  58. 0 0
      docs/en/manuals/images/profiling/webprofiler_frame_data.png
  59. 0 0
      docs/en/manuals/images/profiling/webprofiler_frame_timechart.png
  60. 0 0
      docs/en/manuals/images/profiling/webprofiler_frames_overview.png
  61. 0 0
      docs/en/manuals/images/profiling/webprofiler_frames_plot.png
  62. 0 0
      docs/en/manuals/images/profiling/webprofiler_page.png
  63. 0 0
      docs/en/manuals/images/zerobrane/code.png
  64. 0 0
      docs/en/manuals/images/zerobrane/otherrecommended.png
  65. 0 0
      docs/en/manuals/images/zerobrane/setup.png
  66. binární
      docs/en/manuals/images/zerobrane/show_in_desktop.png
  67. binární
      docs/en/manuals/images/zerobrane/[email protected]
  68. 0 0
      docs/en/manuals/images/zerobrane/startdebug.png
  69. 158 524
      docs/en/manuals/modules.md
  70. 114 0
      docs/en/manuals/profiling.md
  71. 99 0
      docs/en/manuals/zerobrane.md
  72. 9 2
      gulpfile.js

+ 12 - 4
docs/en/en.json

@@ -119,10 +119,22 @@
                         "path": "/manuals/workflow",
                         "name": "Workflow"
                     },
+                    {
+                        "path": "/manuals/hot-reload",
+                        "name": "Hot reloading"
+                    },
                     {
                         "path": "/manuals/lua",
                         "name": "Lua in Defold"
                     },
+                    {
+                        "path": "/manuals/debugging",
+                        "name": "Debugging"
+                    },
+                    {
+                        "path": "/manuals/profiling",
+                        "name": "Profiling"
+                    },
                     {
                         "path": "/manuals/flash",
                         "name": "Defold for Flash users"
@@ -287,10 +299,6 @@
                         "path": "/manuals/input",
                         "name": "Input"
                     },
-                    {
-                        "path": "/manuals/debugging",
-                        "name": "Debugging"
-                    },
                     {
                         "path": "/manuals/modules",
                         "name": "Modules"

+ 84 - 139
docs/en/manuals/debugging.md

@@ -5,198 +5,143 @@ brief: This manual explains the debugging facilities present in Defold.
 
 # Debugging
 
-The simplest way to debug your game in Defold is to use [print debugging](http://en.wikipedia.org/wiki/Debugging#Techniques). The technique is simply to use `print()` or [pprint()](/ref/builtins#pprint) statements to watch variables or indicate the flow of execution. If a game object without a script acts weird, you can just attach a script to it with the sole purpose of debugging.
+Defold contains an integrated Lua debugger with an inspection facility. Together with the built in [profiling tools](/manuals/profiling) it is a powerful tool that can help finding the root cause of bugs or performance issues.
 
-Using any of the printing functions will print to the Console view in the Editor. You can also draw text on screen by posting `draw_text` messages to the `@render` socket:
+## Print and visual debugging
 
-```lua
-msg.post("@render:", "draw_text", {text = "My value: " .. my_val, position = vmath.vector3(200, 200, 0)})
-```
-
-If you run into problems with spatial calculations, like movement and physics, it is often very helpful to visualize the calculations by drawing lines on the screen. Send `draw_line` messages to the `@render` socket:
+The simplest way to debug your game in Defold is to use [print debugging](http://en.wikipedia.org/wiki/Debugging#Techniques). The technique is simply to use `print()` or [`pprint()`](/ref/builtins#pprint) statements to watch variables or indicate the flow of execution. If a game object without a script acts weird, you can just attach a script to it with the sole purpose of debugging. Using any of the printing functions will print to the *Console* view in the editor.  In addition to printing, the engine can also draw debug text and straight lines on the screen. This is done by posting messages to the `@render` socket:
 
 ```lua
-msg.post("@render:", "draw_line", {start_point = my_start, end_point = my_end, color = my_color})
+-- Draw value of "my_val" with debug text on the screen
+msg.post("@render:", "draw_text", { text = "My value: " .. my_val, position = vmath.vector3(200, 200, 0) })
+
+-- Draw debug line between player and enemy on the screen
+local start_p = go.get_position("player")
+local end_p = go.get_position("enemy")
+local color_red = vmath.vector4(1, 0, 0, 1)
+msg.post("@render:", "draw_line", { start_point = start_p, end_point = end_p, color = color_red })
 ```
 
-Lua comes with a debug library that is useful in some situations, particularly if you need to inspect the innards of your Lua environment. You can find more information about it on http://www.lua.org/pil/contents.html#23.
-
-## Debugging Lua scripts with ZeroBrane
-
-Defold engine comes with built-in support for debugging your Lua scripts through the free and open-source Lua IDE _ZeroBrane Studio_. ZeroBrane Studio needs to be installed in order to use the debugging features. The program is cross-platform and runs on both OSX and Windows.
-
-Download "ZeroBrane Studio" from http://studio.zerobrane.com
-
-## ZeroBrane configuration
-
-In order for ZeroBrane to find the files in your project, you need to point it to the location of your Defold project directory. A convenient way of finding this out is by using the <kbd>Show in Finder/Explorer</kbd> option in your Defold project.
-
-1. Right click on *game.project*
-2. Choose <kbd>Show in Finder</kbd>, for OS X users, or *Show in Explorer* for Windows users
-
-OS X:
-
-![Show in Finder](images/debugging/showinfind.png)
+The visual debug messages adds data to the rendering pipeline and is drawn as part of the regular render pipeline.
 
-Windows:
+* `"draw_line"` adds data that is rendered with the `render.draw_debug3d()` function in the render script.
+* `"draw_text"` is rendered with the "/builtins/fonts/system_font.font" that uses the "/builtins/fonts/system_font.material" material.
 
-![Show in Explorer](images/debugging/showinwin.png)
+Note that you probably want to update this data every frame so posting the messages in the `update()` function is a good idea.
 
-## To set up ZeroBrane
+## Running the debugger
 
-To set up ZeroBrane, select <kbd>Project ▸ Project Directory ▸ Choose...</kbd>:
+To run the debugger, either <kbd>Debug ▸ Run with Debugger</kbd> which starts up the game with the debugger attached, or select <kbd>Debug ▸ Attach Debugger</kbd> to attach the debugger to an already running game.
 
-![Auto completion](images/debugging/setup.png)
+![overview](images/debugging/overview.png){srcset="images/debugging/[email protected] 2x"}
 
-Once this has been set up to match the current Defold project directory, it should be possible to see the directory tree of the Defold project in ZeroBrane, and to navigate and open the files.
+As soon as the debugger is attached, you have control of the execution of the game through the debugger control buttons in the console, or through the <kbd>Debug</kbd> menu:
 
-Other recommended, but not necessary configuration changes can be found further down in the document.
+Break
+: ![pause](images/debugging/pause.svg){width=60px .left} 
+  Break execution of the game immediately. The game will break at its current point. You are now able to inspect the state of the game, advance the game step by step, or continue running it until the next breakpoint. The current point of execution is marked in the code editor:
+  
+  ![script](images/debugging/script.png){srcset="images/debugging/[email protected] 2x"}
 
-## Starting the debugging server
+Continue
+: ![play](images/debugging/play.svg){width=60px .left}
+  Continue running the game. The game code will continue to run until you either press pause or the execution hits a breakpoint that you have set. If execution breaks at a set breakpoint, the the execution point is marked in the code editor on top of the breakpoint marker:
 
-Before starting a debugging session, the ZeroBrane built-in debugging server needs to be started. The menu option for starting it can be found under the <kbd>Project</kbd> menu. Just select <kbd>Project ▸ Start Debugger Server</kbd>:
+  ![break](images/debugging/break.png){srcset="images/debugging/[email protected] 2x"}
 
-![Auto completion](images/debugging/startdebug.png)
+Stop
+: ![stop](images/debugging/stop.svg){width=60px .left}
+  Stop the debugger. Pressing this button will immediately stop the debugger, detach it from the game and terminate the running game.
 
-## Connecting your application to the debugger
+Step Over
+: ![step over](images/debugging/step_over.svg){width=60px .left}
+  Advance execution of the program one step. If the execution involves running another Lua function, the execution _will not step into the function_ but continue running and stop on the next line below the function call. In this example, if the user presses "step over", the debugger will execute code and stop at the `end` statement below the line with the call to the function `nextspawn()`:
 
-Debugging can be started at any point in the lifetime of the Defold application, but needs to be actively initiated from Lua script. The Lua code to start a debugging session looks like this:
+  ![step](images/debugging/step.png){srcset="images/debugging/[email protected] 2x"}
 
 ::: sidenote
-If your game exits when `dbg.start()` is called, it might be because ZeroBrane has detected a problem and sends the exit command to the game. For some reason, ZeroBrane needs a file opened to start the debug session, otherwise it will output:
-"Can't start debugging without an opened file or with the current file not being saved 'untitled.lua')."
-In ZeroBrane, open the file you added `dbg.start()` to fix this error.
+A line of Lua code does not correspond to a single expression. Stepping in the debugger moves ahead one expression at a time, meaning that currently you may have to hit the step button more than once to advance to the next line.
 :::
 
-```lua
-local dbg = require "builtins.scripts.mobdebug"
-dbg.start()
-```
+Step Into
+: ![step in](images/debugging/step_in.svg){width=60px .left}
+  Advance execution of the program one step. If the execution involves running another Lua function, the execution _will step into the function_. Calling the function adds an entry to the call stack. You can click each entry in the call stack list to view the entry point and the content of all variables in that closure. Here, the user has stepped into the function `nextspawn()`:
 
-By inserting the above code into the application, it will connect to ZeroBrane’s debugging server (through "localhost", by default) and pause at the next statement to be executed.
+  ![step into](images/debugging/step_into.png){srcset="images/debugging/[email protected] 2x"}
 
-```txt
-Debugger server started at localhost:8172.
-Mapped remote request for '/' to '/Users/my_user/Documents/Projects/Defold_project/'.
-Debugging session started in '/Users/my_user/Documents/Projects/Defold_project'.
-```
+Step Out
+: ![step out](images/debugging/step_out.svg){width=60px .left}
+  Continue execution until it returns from the current function. If you have stepped execution into a function, pressing the button "step out" will continue execution until the function returns.
 
-Now it is possible to use the debugging features available in ZeroBrane; you can step, inspect, add and remove breakpoints etc.
+Setting and clearing breakpoints
+: You can set an arbitrary number of breakpoints in your Lua code. When the game runs with the debugger attached, it will stop execution at the next breakpoint it encounters and wait for further interaction from you.
 
-::: sidenote
-The debugging will only be enabled for the lua context from where debugging is initiated. Enabling "shared_state" in game.project means you can debug your whole application no matter where you started.
-:::
+  ![add breakpoint](images/debugging/add_breakpoint.png){srcset="images/debugging/[email protected] 2x"}
 
-![Auto completion](images/debugging/code.png)
+  To set or clear a breakpoint, click in the column just right of the line numbers in the code editor. You can also select <kbd>Edit ▸ Toggle Breakpoint</kbd> from the menu.
 
-Should the connection attempt fail (possibly because the debugging server is not running), your application will continue to run as normal after the connection attempt has been made.
+Evaluating Lua expressions
+: With the debugger attached and the game stopped at a breakpoint, a Lua runtime is available with the current context. Type Lua expressions in the bottom of the console and press <kbd>Enter</kbd> to evaluate them:
 
-## Remote debugging
+  ![console](images/debugging/console.png){srcset="images/debugging/[email protected] 2x"}
 
-As debugging happens over regular network connections (TCP), this allows for debugging remotely. This means it is possible to debug your application while it is running on a mobile device.
+  It is currently not possible to modify variables through the evaluator.
 
-The only change needed is to the command which starts the debugging. By default, `start()` will try to connect to localhost, but for remote debugging, we need to manually specify the address to ZeroBrane’s debugging server, like this:
+Detaching the debugger
+: Select <kbd>Debug ▸ Detach Debugger</kbd> to detach the debugger from the game. It will continue running immediately.
 
-```lua
-local dbg = require "builtins.scripts.mobdebug"
-dbg.start("192.168.5.101")
-```
-
-This also means it is important to make sure to have network connectivity from the remote device, and that any firewalls or similar software allows TCP connections through on port 8172. Otherwise the application might stall when launching when it attempts to make the connection to your debugging server.
-
-## Other recommended ZeroBrane setting
+## Debugging on mobile devices
 
-It is possible to make ZeroBrane automatically open Lua script files during debugging. This makes it possible to step into functions in other source files without having to open them manually.
+Some issues can be hard to debug with the editor debugger. Diagnosing problems such as native crashes and out of memory issues may need you to connect to the devices with USB cable and make use of a terminal.
 
-The first step is to access the editor configuration file. It is recommended that you change the user version of the file.
+Android
+: Once your game is launched on your Android device, you can view all program output and crash stacktraces using the "adb" tool, which is part of the Android SDK. Documentation for "adb" and installation links can be found here: https://developer.android.com/studio/command-line/adb.html
 
-- Select menu:Edit[Preferences > Settings: User]
-- Add the following to the configuration file:
+  Once installed and setup, connect your device with USB, open a terminal and run:
 
   ```txt
-  - to automatically open files requested during debugging
-  editor.autoactivate = true
+  cd <path_to_android_sdk>/platform-tools/
+  adb logcat
   ```
 
-- Restart ZeroBrane
-
-![Other recommended settings](images/debugging/otherrecommended.png)
-
-## Hot reloading
+  The device will then dump all the output to the current terminal, along with any prints from the game.
 
-Defold allows you to perform hot reloading of resources. When developing a game this feature helps speed up certain task enormously. It allows you to change scripts in a game while it is running live. Common use-cases are to tweak gameplay parameters or to perform debugging on a running game.
+iOS
+: On iOS you can attach the LLDB debugger to a game running on device. To debug a game it needs to be signed with a “Apple Developer Provisioning Profile” that include the device you want to debug on. Bundle the game from the editor and supply the provisioning profile in the bundle dialog (bundling for iOS is only available on macOS).
 
-To reload a changed resource, simply select the menu item <kbd>Edit ▸ Reload Resource</kbd> or press the corresponding shortcut on the keyboard:
+  To launch the game and attach the debugger you will need a tool called [ios-deploy](https://github.com/phonegap/ios-deploy). Install and debug your game by running the following in a terminal:
 
-![Reloading resources](images/debugging/debugging_hot_reload.png)
-
-Every script component can define a `on_reload()` function. If it exists it will be called anytime a script is reloaded into the game from the editor:
-
-```lua
-function on_reload(self)
-    -- Print the current velocity
-    print(self.velocity)
-    -- Zero the velocity
-    self.velocity = vmath.vector3()
-end
-```
-
-## Visual profiler
-
-The Defold engine is also able to display profiling information in a running game. This can be helpful when debugging or optimizing.
-
-```lua
-function on_reload(self)
-    -- Turn on profiler on hot reload.
-    msg.post("@system:", "toggle_profile")
-end
-```
-
-The profiler displays live information on the running application:
-
-![Visual profiler](images/debugging/debugging_profiling.png)
-
-## Web profiler
-
-While running the game, a web-based profiler can be accessed that provides detailed profiling information. It allows you to sample a series of data points and then analyze it in detail.
-
-To access the profiler:
-
-1. Start your game on your target device.
-2. Open a web browser and point it to `http://<device IP>:8002` where `<device IP>` is the IP address of the device.
-
-If you are running your game on your desktop computer, _http://localhost:8002_ would bring up the profiler. You can find the IP numbers of your target devices in the <kbd>Project ▸ Target</kbd> menu.
-
-![Web profiler](images/debugging/webprofiler_page.png)
-
-The profiler is divided into 4 sections that all give different views into the current sample data. To update the sample data, press the *Capture* button at the top.
-
-## Frames overview
+  ```txt
+  ios-deploy --debug --bundle <path_to_game.app> # NOTE: not the .ipa file
+  ```
 
-The frames overview plots the currently sampled 20 frames side by side. The height of each bar shows the time spent in the frame. The number on the left hand side shows the max time spent in a frame in the current sample data.
+  This will install the app on your device, start it and automatically attach a LLDB debugger to it. If you are new to LLDB, read [Getting Started with LLDB](https://developer.apple.com/library/content/documentation/IDEs/Conceptual/gdb_to_lldb_transition_guide/document/lldb-basics.html).
 
-![Frames overview](images/debugging/webprofiler_frames_overview.png)
 
-Below the frames overview is a detailed frame data view. You can click on any frame bar in the overview to show the data for that specific frame in the data view. The frame timechart at the bottom of the page also updates to show the clicked frame's data.
+## Extracting the log.txt file
 
-## Frame data
+If you enable the *Write Log* setting in "game.project", any game output will be written to disk, to a file called "log.txt". Here is how you extract the file if you run the game on device:
 
-The frame data view is a table where all data for the currently selected frame is broken down into detail. You can view how many milliseconds are spent in each engine scope (to the left) and also see sample points within the scopes (middle column). On the right hand side is a table of counters. The numbers presented are counters so it is easy to, for instance, track the number of draw calls required for each frame in the sample data.
+iOS
+: Connect your device to a computer with macOS and Xcode installed.
+  
+  Open Xcode and go to <kbd>Window ▸ Devices and Simulators</kbd>.
 
-![Frame data](images/debugging/webprofiler_frame_data.png)
+  Select your device in the list, then select the relevant app in the *Installed Apps* list.
 
-Ticking the checkbox associated with a sample point or counter adds that data to the plot below.
+  Click the cog icon below the list and select <kbd>Download Container...</kbd>.
 
-## Frames plot
+  ![download container](images/debugging/download_container.png){srcset="images/debugging/[email protected] 2x"}
 
-The frames plot view displays a plot over all sampled frames using the data selected in the frame data table, frame number on the X axis and time in milliseconds on the Y axis. Each selected data point is drawn in the color specified in the frame data table.
+  Once the container has been extracted it will be shown in *Finder*. Right click the container and select <kbd>Show Package Content</kbd>. Locate the file "log.txt", which should be located in "AppData/Documents/".
 
-![Frames plot](images/debugging/webprofiler_frames_plot.png)
+Android
+: The ability to extract the "log.txt" depends on OS version and manufacturer. Here is a short and simple step by step guide: https://stackoverflow.com/a/48077004/129360
 
-## Frame time chart
+## Running the ZeroBrane external debugger
 
-The frame time chart breaks the frame down visually making it is very easy to inspect where the engine spends its time during the selected frame.
+In addition to the built in debugger, it is also possible to use the Lua IDE _ZeroBrane Studio_ as an external Lua debugger. Please refer to the [ZeroBrane debugging manual](/manuals/zerobrane) for details on how to set up and run the program with Defold.
 
-![Frame timechart](images/debugging/webprofiler_frame_timechart.png)
+## Lua debug library
 
-(Some of the graphic assets used are made by Kenney: http://kenney.nl/assets)
+Lua comes with a debug library that is useful in some situations, particularly if you need to inspect the innards of your Lua environment. You can find more information about it here: http://www.lua.org/pil/contents.html#23.

+ 17 - 1
docs/en/manuals/glossary.md

@@ -47,13 +47,17 @@ Components are used to give specific expression and/or functionality to game obj
 
 ![Cubemap](images/icons/cubemap.png){.left} A cubemap is a special type of texture that consists of 6 different textures that are mapped on the sides of a cube. This is useful for rendering skyboxes and different kinds of reflection and illumination maps.
 
+## Debugging
+
+At some point your game will behave in an unexpected way and you need to figure out what is wrong. Learning how to debug is an art and fortunately Defold ships with a built in debugger to help you out. See the [Debugging manual](/manuals/debugging) for more information.
+
 ## Factory
 
 ![Factory](images/icons/factory.png){.left} In some situations you cannot manually place all needed game objects in a collection, you have to create the game objects dynamically, on the fly. For instance, a player might fire bullets and each shot should be dynamically spawned and sent off whenever the player presses the trigger. To create game objects dynamically (from a pre-allocated pool of objects), you use a factory component. See the [Factory manual](/manuals/factory) for details.
 
 ## Font
 
-![Font file](images/icons/font.png){.left} A Font resource is built from a TrueType or OpenType font file. The Font specifies which size to render the font in and what type of decoration (outline and shadow) the rendered font should have. Fonts are used by GUI and Label components.
+![Font file](images/icons/font.png){.left} A Font resource is built from a TrueType or OpenType font file. The Font specifies which size to render the font in and what type of decoration (outline and shadow) the rendered font should have. Fonts are used by GUI and Label components. See the [Font manual](/manuals/font/) for details.
 
 ## Fragment shader
 
@@ -75,6 +79,10 @@ Components are used to give specific expression and/or functionality to game obj
 
 ![GUI script](images/icons/script.png){.left} GUI scripts are used to control the behaviour of GUI components. They control GUI animations and how the user interacts with the GUI. See the [Lua in Defold manual](/manuals/lua) for details on how Lua scripts are used in Defold.
 
+## Hot reload
+
+The Defold editor allows you to update content in an already running game, on desktop and device. This feature is extremely powerful and can improve the development workflow a lot. See the [Hot reload manual](/manuals/hot-reload) for more information.
+
 ## Input binding
 
 ![Input binding](images/icons/input-binding.png){.left} Input binding files define how the game should interpret hardware input (mouse, keyboard, touchscreen and gamepad). The file binds hardware input to high level input _actions_ like "jump" and "move_forward". In script components that listen to input you are able to script the actions the game or app should take given certain input. See the [Input documentation](/manuals/input) for details.
@@ -87,6 +95,10 @@ Components are used to give specific expression and/or functionality to game obj
 
 ![Game object](images/icons/builtins.png){.left} Defold allows you to share data between projects through a powerful library mechanism. You can use it to set up shared libraries that are accessible from all your projects, either for yourself or across the whole team. Read more about the library mechanism in the [Libraries documentation](/manuals/libraries).
 
+## Lua language
+
+The Lua programming language is used in Defold to create game logic. Lua is a powerful, efficient, very small scripting language. It supports procedural programming, object-oriented programming, functional programming, data-driven programming, and data description. You can read more about the language on the official Lua homepage at https://www.lua.org/ and in the [Lua in Defold manual](/manuals/lua).
+
 ## Lua module
 
 ![Lua module](images/icons/lua-module.png){.left} Lua modules allow you to structure your project and create reusable library code. Read more about it in the [Lua modules manual](/manuals/modules/)
@@ -115,6 +127,10 @@ Here, `"#explosion"` is the address of the current object's sound component. `"p
 
 ![ParticleFX](images/icons/particlefx.png){.left} Particles are very useful for creating nice visual effects, particularly in games. you can use them to create fog, smoke, fire, rain or falling leaves. Defold contains a powerful particle effects editor that allows you to build and tweak effects while you run them real time in your game. The [ParticleFX documentation](/manuals/particlefx) gives you the details on how that works.
 
+## Profiling
+
+Good performance is key in games and it is vital that you are able to do performance and memory profiling to measure your game and identify performance bottlenecks and memory problems that needs to be fixed. See the [Profiling manual](/manuals/profiling) for more information on the profiling tools available for Defold.
+
 ## Render
 
 ![Render](images/icons/render.png){.left} Render files contain settings used when rendering the game to the screen. Render files define which Render script to use for rendering and which materials to use. See the [Render manual](/manuals/render/) for more details.

+ 122 - 0
docs/en/manuals/hot-reload.md

@@ -0,0 +1,122 @@
+---
+title: Hot reloading
+brief: This manual explains the hot reloading feature in Defold.
+---
+
+# Hot reloading resources
+
+Defold allows you to perform hot reloading of resources. When developing a game this feature helps speed up certain task enormously. It allows you to change code and content of a game while it is running live. Common use-cases are:
+
+- To tweak gameplay parameters in Lua scripts.
+- To edit and tweak graphical elements (such as particle effects or GUI elements) and view the results in the proper context.
+- To edit and tweak shader code and view the results in the proper context.
+- To facilitate game testing by restarting levels, setting state and so forth---without stopping the game.
+
+## How to hot reload
+
+Start your game from the editor (<kbd>Project ▸ Build</kbd>).
+
+To then reload an updated resource  simply select the menu item <kbd>File ▸ Hot Reload</kbd> or press the corresponding shortcut on the keyboard:
+
+![Reloading resources](images/hot-reload/menu.png){srcset="images/hot-reload/[email protected] 2x"}
+
+## Hot reloading on device
+
+Hot reloading works wirelessly on device as well as on desktop. To use it on device, run a debug build of your game, or the [development app](/manuals/dev-app) on your mobile device, then chose it as target in the editor:
+
+![target device](images/hot-reload/target.png){srcset="images/hot-reload/[email protected] 2x"}
+
+Now when you build and run, the editor uploads all assets to the running app on the device and starts the game. From thereon, any file you hot reload will update on the device.
+
+For instance, to add a couple of buttons to a GUI that is being displayed in a running game on your phone, just open the GUI file:
+
+![reload gui](images/hot-reload/gui.png){srcset="images/hot-reload/[email protected] 2x"}
+
+Add the new buttons, save and hot reload the GUI file. You can now see the new buttons on the phone screen:
+
+![reloaded gui](images/hot-reload/gui-reloaded.png){srcset="images/hot-reload/[email protected] 2x"}
+
+When you hot reload a file, the engine will print each reloaded resource file in the console.
+
+## Reloading scripts
+
+Any Lua script file that is reloaded will be re-executed in the running Lua environment. 
+
+```lua
+local my_value = 10
+
+function update(self, dt)
+    print(my_value)
+end
+```
+
+Changing `my_value` to 11 and hot reloading the file will have immediate effect:
+
+```text
+...
+DEBUG:SCRIPT: 10
+DEBUG:SCRIPT: 10
+DEBUG:SCRIPT: 10
+INFO:RESOURCE: /main/hunter.scriptc was successfully reloaded.
+DEBUG:SCRIPT: 11
+DEBUG:SCRIPT: 11
+DEBUG:SCRIPT: 11
+...
+```
+
+Note that hot reloading does not alter the execution of the lifecycle functions. There is no call to `init()` on hot reload, for instance. If you redefine the lifecycle functions, the new versions will be used though.
+
+## Reloading Lua modules
+
+As long as you add variables to the global scope in a module file, reloading the file will alter these globals:
+
+```lua
+--- my_module.lua
+my_module = {}
+my_module.val = 10
+```
+
+```lua
+-- user.script
+require "my_module"
+
+function update(self, dt)
+    print(my_module.val) -- hot reload "my_module.lua" and the new value will print
+end
+```
+
+A common Lua module pattern is to construct a local table, populate it and then return it:
+
+```lua
+--- my_module.lua
+local M = {} -- a new table object is created here
+M.val = 10
+return M
+```
+
+```lua
+-- user.script
+local mm = require "my_module"
+
+function update(self, dt)
+    print(mm.val) -- will print 10 even if you change and hot reload "my_module.lua"
+end
+```
+
+Changing and reloading "my_module.lua" will _not_ change the behavior of "user.script". See [the Modules manual](/manuals/modules) for more information on why, and how to avoid this pitfall.
+
+## The on_reload() function
+
+Every script component can define a `on_reload()` function. If it exists it will be called anytime the script is reloaded. This is useful for inspecting or changing data, sending messages and so forth:
+
+```lua
+function on_reload(self)
+    print(self.velocity)
+
+    msg.post("/level#controller", "setup")
+end
+```
+
+## Reloading shader code
+
+When reloading vertex and fragment shaders, the GLSL code is recompiled by the graphics driver and uploaded to the GPU. If the shader code causes a crash, which is easily done since GLSL is written at a very low level, it will take the engine down.

binární
docs/en/manuals/images/debugging/add_breakpoint.png


binární
docs/en/manuals/images/debugging/[email protected]


binární
docs/en/manuals/images/debugging/break.png


binární
docs/en/manuals/images/debugging/[email protected]


binární
docs/en/manuals/images/debugging/callstack.png


binární
docs/en/manuals/images/debugging/[email protected]


binární
docs/en/manuals/images/debugging/console.png


binární
docs/en/manuals/images/debugging/[email protected]


binární
docs/en/manuals/images/debugging/debugging_hot_reload.png


binární
docs/en/manuals/images/debugging/debugging_profiling.png


binární
docs/en/manuals/images/debugging/download_container.png


binární
docs/en/manuals/images/debugging/[email protected]


binární
docs/en/manuals/images/debugging/overview.png


binární
docs/en/manuals/images/debugging/[email protected]


+ 1 - 0
docs/en/manuals/images/debugging/pause.svg

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"><rect id="Page-2" serif:id="Page 2" x="0" y="0" width="16" height="16" style="fill:none;"/><g id="Layer-1" serif:id="Layer 1"><path d="M5.5,3l-2,0c-0.276,0 -0.5,0.224 -0.5,0.5l0,9c0,0.276 0.224,0.5 0.5,0.5l2,0c0.276,0 0.5,-0.224 0.5,-0.5l0,-9c0,-0.276 -0.224,-0.5 -0.5,-0.5m6.5,0.5l0,9c0,0.276 -0.224,0.5 -0.5,0.5l-2,0c-0.276,0 -0.5,-0.224 -0.5,-0.5l0,-9c0,-0.276 0.224,-0.5 0.5,-0.5l2,0c0.276,0 0.5,0.224 0.5,0.5" style="fill:#8f9295;fill-rule:nonzero;"/></g></svg>

+ 1 - 0
docs/en/manuals/images/debugging/play.svg

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"><rect id="Page-1" serif:id="Page 1" x="0" y="0" width="16" height="16" style="fill:none;"/><clipPath id="_clip1"><rect id="Page-11" serif:id="Page 1" x="0" y="0" width="16" height="16"/></clipPath><g clip-path="url(#_clip1)"><g id="Layer-1" serif:id="Layer 1"><path d="M11.786,8.408l-7.226,4.262c-0.257,0.151 -0.56,-0.07 -0.56,-0.408l0,-8.523c0,-0.34 0.303,-0.56 0.56,-0.409l7.226,4.262c0.285,0.168 0.285,0.648 0,0.816" style="fill:#8f9295;fill-rule:nonzero;"/></g></g></svg>

binární
docs/en/manuals/images/debugging/script.png


binární
docs/en/manuals/images/debugging/[email protected]


binární
docs/en/manuals/images/debugging/showinfind.png


binární
docs/en/manuals/images/debugging/showinwin.png


binární
docs/en/manuals/images/debugging/step.png


binární
docs/en/manuals/images/debugging/[email protected]


+ 1 - 0
docs/en/manuals/images/debugging/step_in.svg

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"><rect id="Page-4" serif:id="Page 4" x="0" y="0" width="16" height="16" style="fill:none;"/><g id="Layer-1" serif:id="Layer 1"><path d="M11.633,5.764c-0.303,-0.283 -0.776,-0.267 -1.06,0.034l-0.823,0.878l0,-3.676c0,-0.414 -0.336,-0.75 -0.75,-0.75c-0.414,0 -0.75,0.336 -0.75,0.75l0,3.704l-0.857,-0.803c-0.303,-0.284 -0.777,-0.268 -1.06,0.033c-0.283,0.303 -0.268,0.777 0.034,1.06l2.189,2.053c0.139,0.131 0.322,0.203 0.513,0.203l0.024,0c0.198,-0.007 0.387,-0.092 0.522,-0.237l2.052,-2.188c0.283,-0.303 0.269,-0.777 -0.034,-1.061m-0.792,6.736c0,1.016 -0.824,1.841 -1.841,1.841c-1.016,0 -1.841,-0.825 -1.841,-1.841c0,-1.017 0.825,-1.841 1.841,-1.841c1.017,0 1.841,0.824 1.841,1.841" style="fill:#8f9295;fill-rule:nonzero;"/></g></svg>

binární
docs/en/manuals/images/debugging/step_into.png


binární
docs/en/manuals/images/debugging/[email protected]


+ 1 - 0
docs/en/manuals/images/debugging/step_out.svg

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"><rect id="Page-5" serif:id="Page 5" x="0" y="0" width="16" height="16" style="fill:none;"/><g id="Layer-1" serif:id="Layer 1"><path d="M11.133,4.317l-2.188,-2.052c-0.145,-0.136 -0.321,-0.217 -0.538,-0.203c-0.198,0.006 -0.386,0.091 -0.522,0.236l-2.052,2.189c-0.283,0.302 -0.268,0.777 0.034,1.06c0.145,0.136 0.329,0.203 0.513,0.203c0.2,0 0.399,-0.079 0.547,-0.237l0.823,-0.878l0,3.865c0,0.414 0.336,0.75 0.75,0.75c0.414,0 0.75,-0.336 0.75,-0.75l0,-3.893l0.858,0.804c0.301,0.283 0.777,0.268 1.059,-0.034c0.283,-0.302 0.269,-0.777 -0.034,-1.06m-0.792,8.183c0,1.017 -0.824,1.841 -1.841,1.841c-1.016,0 -1.841,-0.824 -1.841,-1.841c0,-1.016 0.825,-1.841 1.841,-1.841c1.017,0 1.841,0.825 1.841,1.841" style="fill:#8f9295;fill-rule:nonzero;"/></g></svg>

+ 1 - 0
docs/en/manuals/images/debugging/step_over.svg

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"><rect id="Page-3" serif:id="Page 3" x="0" y="0" width="16" height="16" style="fill:none;"/><g id="Layer-1" serif:id="Layer 1"><path d="M13.893,5.308c-0.064,-0.409 -0.449,-0.689 -0.857,-0.624c-0.41,0.064 -0.689,0.448 -0.624,0.857l0.169,1.079c-1.171,-0.878 -2.603,-1.37 -4.081,-1.37c-1.902,0 -3.733,0.807 -5.023,2.213c-0.28,0.305 -0.259,0.78 0.046,1.06c0.306,0.279 0.779,0.26 1.059,-0.046c1.007,-1.098 2.435,-1.727 3.918,-1.727c1.205,0 2.368,0.421 3.304,1.165l-1.265,0.199c-0.409,0.065 -0.688,0.448 -0.624,0.858c0.058,0.37 0.377,0.633 0.74,0.633c0.039,0 0.078,-0.003 0.117,-0.009l2.964,-0.467c0.409,-0.065 0.688,-0.448 0.624,-0.858l-0.467,-2.963Zm-3.553,7.192c0,1.016 -0.823,1.841 -1.84,1.841c-1.017,0 -1.84,-0.825 -1.84,-1.841c0,-1.017 0.823,-1.841 1.84,-1.841c1.017,0 1.84,0.824 1.84,1.841" style="fill:#8f9295;fill-rule:nonzero;"/></g></svg>

+ 1 - 0
docs/en/manuals/images/debugging/stop.svg

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"><rect id="Page-6" serif:id="Page 6" x="0" y="0" width="16" height="16" style="fill:none;"/><g id="Layer-1" serif:id="Layer 1"><path d="M13,3.909l0,8.182c0,0.502 -0.407,0.909 -0.909,0.909l-8.182,0c-0.502,0 -0.909,-0.407 -0.909,-0.909l0,-8.182c0,-0.502 0.407,-0.909 0.909,-0.909l8.182,0c0.502,0 0.909,0.407 0.909,0.909" style="fill:#8f9295;fill-rule:nonzero;"/></g></svg>

binární
docs/en/manuals/images/debugging/variables.png


binární
docs/en/manuals/images/debugging/[email protected]


binární
docs/en/manuals/images/hot-reload/gui-reloaded.png


binární
docs/en/manuals/images/hot-reload/[email protected]


binární
docs/en/manuals/images/hot-reload/gui.png


binární
docs/en/manuals/images/hot-reload/[email protected]


binární
docs/en/manuals/images/hot-reload/menu.png


binární
docs/en/manuals/images/hot-reload/[email protected]


binární
docs/en/manuals/images/hot-reload/target.png


binární
docs/en/manuals/images/hot-reload/[email protected]


binární
docs/en/manuals/images/modules/modules_new.png


binární
docs/en/manuals/images/modules/modules_new_name.png


binární
docs/en/manuals/images/modules/new_name.png


binární
docs/en/manuals/images/modules/[email protected]


binární
docs/en/manuals/images/profiling/android_profiler.png


binární
docs/en/manuals/images/profiling/build_report.png


binární
docs/en/manuals/images/profiling/[email protected]


binární
docs/en/manuals/images/profiling/build_report_html.png


binární
docs/en/manuals/images/profiling/[email protected]


binární
docs/en/manuals/images/profiling/gapid.png


binární
docs/en/manuals/images/profiling/instruments.png


binární
docs/en/manuals/images/profiling/[email protected]


binární
docs/en/manuals/images/profiling/opengl.png


binární
docs/en/manuals/images/profiling/[email protected]


binární
docs/en/manuals/images/profiling/visual_profiler.png


+ 0 - 0
docs/en/manuals/images/debugging/webprofiler_frame_data.png → docs/en/manuals/images/profiling/webprofiler_frame_data.png


+ 0 - 0
docs/en/manuals/images/debugging/webprofiler_frame_timechart.png → docs/en/manuals/images/profiling/webprofiler_frame_timechart.png


+ 0 - 0
docs/en/manuals/images/debugging/webprofiler_frames_overview.png → docs/en/manuals/images/profiling/webprofiler_frames_overview.png


+ 0 - 0
docs/en/manuals/images/debugging/webprofiler_frames_plot.png → docs/en/manuals/images/profiling/webprofiler_frames_plot.png


+ 0 - 0
docs/en/manuals/images/debugging/webprofiler_page.png → docs/en/manuals/images/profiling/webprofiler_page.png


+ 0 - 0
docs/en/manuals/images/debugging/code.png → docs/en/manuals/images/zerobrane/code.png


+ 0 - 0
docs/en/manuals/images/debugging/otherrecommended.png → docs/en/manuals/images/zerobrane/otherrecommended.png


+ 0 - 0
docs/en/manuals/images/debugging/setup.png → docs/en/manuals/images/zerobrane/setup.png


binární
docs/en/manuals/images/zerobrane/show_in_desktop.png


binární
docs/en/manuals/images/zerobrane/[email protected]


+ 0 - 0
docs/en/manuals/images/debugging/startdebug.png → docs/en/manuals/images/zerobrane/startdebug.png


+ 158 - 524
docs/en/manuals/modules.md

@@ -5,456 +5,120 @@ brief: Lua modules allow you to structure your project and create reusable libra
 
 # Lua modules
 
-Lua modules allow you to structure your project and create reusable library code. It is generally a good idea to avoid duplication in your projects. Script code that replicates identical behavior between different game objects can simply be copied and pasted. However, if instead the script code could be shared between the game objects, any changes to the single script code instance would instantly affect both game objects.
+Lua modules allow you to structure your project and create reusable library code. It is generally a good idea to avoid duplication in your projects. Defold allows you to use Lua's module functionality to include script files into other script files. This allows you to encapsulate functionality (and data) in an external script file for reuse in game object and GUI script files.
 
-Defold allows you to include script files into other script files which allows you to share code. Moreover, Lua modules can be used to encapsulate functionality and data in an external script file for reuse in game object and GUI script files.
+## Requiring Lua files
 
-## Requiring files
+Lua code stored in files with file ending ".lua" somewhere in your game project structure can be required into script and gui script files. To create a new Lua module file, right click the folder you want to create it in in the *Assets* view, then select <kbd>New... ▸ Lua Module</kbd>. Give the file a unique name and press <kbd>Ok</kbd>:
 
-Suppose we are building an application featuring butterflies of different kinds. We want to create some behaviors for these butterflies and share those behaviors. To do so we create a game object with a script file:
+![new file](images/modules/new_name.png){srcset="images/modules/[email protected] 2x"}
 
-![Blue butterfly](images/modules/modules_blue_butterfly.png)
-
-We put the following code in *blue_butterfly.script*:
+Suppose the following code is added to the file "main/anim.lua":
 
 ```lua
-require "modules_example.flying"
-
-function init(self)
-    fly_randomly()
-end
-
-function on_message(self, message_id, message, sender)
-    if message_id == hash("fly_randomly_done") then
-        fly_randomly()
+function direction_animation(direction, char)
+    local d = ""
+    if direction.x > 0 then
+        d = "right"
+    elseif direction.x < 0 then
+        d = "left"
+    elseif direction.y > 0 then
+        d = "up"
+    elseif direction.y < 0 then
+        d = "down"
     end
+    return hash(char .. "-" .. d)
 end
 ```
 
-The idea is that we call `fly_randomly()` at `init()` which will cause the butterfly to animate to a new random position some distance relative to its origin. When the animation is done, we get a `fly_randomly_done` message back and immediately send the butterfly to a new random position (some distance relative its origin).
-
-The first line `require 'modules_example.flying'` reads the script file *flying.lua* in the folder *modules_example* (where the application logic is stored) into the engine.
-
-::: sidenote
-The syntax of the filename string provided to `require` is a bit special. Lua will replace '.' characters in the filename string with path separators: '/' on Mac OS X and Linux and '\\' on Windows.
-:::
-
-To create *flying.lua*, just add a new Lua module file to your project and name it:
-
-![New module](images/modules/modules_new.png)
-
-![New module name](images/modules/modules_new_name.png)
+Then it's possible for any script to require this file and use the function:
 
 ```lua
--- We need to store the original position.
-local origin
-
--- Crudely fly to a random position at "radius" distance
--- from the original position
--- This function sends back a "fly_randomly_done" message when it's done.
-function fly_randomly(radius)
-    -- Radius is 100 unless specified
-    radius = radius or 100
-    local go_id = go.get_id()
-    -- Store original location
-    if origin == nil then
-        origin = go.get_world_position(go_id)
-    end
+require "main.anim"
 
-    -- Figure out a random position at max distance
-    -- "radius" from origin
-    local rand_angle = math.random(0, 3.141592 * 2)
-    local rand_radius = math.random(radius)
-    local offset = vmath.rotate(vmath.quat_rotation_z(rand_angle),
-                                vmath.vector3(rand_radius, 0, 0))
-    local rand_pos = origin + offset
-    -- Set a random duration scaled against the radius to prevent
-    -- too fast animation.
-    local rand_duration = math.random(radius) / 100 + (radius / 200)
-    -- Animate, then send a message back when completed
-    go.animate(".", "position", go.PLAYBACK_ONCE_FORWARD,
-        rand_pos, go.EASING_INOUTSINE, rand_duration, 0.0,
-        function ()
-            msg.post("#", "fly_randomly_done")
-        end)
-end
-```
-
-This code works pretty well and it makes the butterfly animate between random positions around its original location. Now, we add a yellow butterfly game object to the collection:
-
-![Blue and yellow butterflies](images/modules/modules_blue_and_yellow.png)
-
-The code for flying randomly already exists, so creating the script for the yellow butterfly is straightforward:
-
-```lua
-require "modules_example.flying"
-
-function init(self)
-    -- Yellow butterflies have a wider flying range.
-    fly_randomly(200)
-end
+function update(self, dt)
+    -- update position, set direction etc
+    ...
 
-function on_message(self, message_id, message, sender)
-    if message_id == hash("fly_randomly_done") then
-        fly_randomly(200)
+    -- set animation
+    local anim = direction_animation(self.dir, "player")
+    if anim ~= self.current_anim then
+        msg.post("#sprite", "play_animation", { id = anim })
+        self.current_anim = anim
     end
 end
 ```
 
-When we run the code we find that the two butterflies join up and start to fly relative to the same origin. To understand what is happening here, recall how Defold manages [Lua contexts](/manuals/lua).
-
-What happens with the blue and yellow butterflies is an unfortunate side effect of sharing global data between game objects. Here is the definition of the variable origin:
-
-```lua
--- We need to store the original position.
-local origin
-```
-
-It is defined "local" which means that it is local to the current Lua context. Since all game objects are evaluated in the same Lua context, the yellow and blue butterfly will use exactly the same variable origin. One of the butterfly objects will set the variable to its origin, then the other butterfly will read and use the same value:
-
-```lua
--- "origin" is not set if someone in the same context
--- has already set it...
-if origin == nil then
-    origin = go.get_world_position(go_id)
-end
-```
-
-We’ll soon see how we can easily fix this bug, but first we should address a more subtle problem.
-
-## Name spaces
+The function `require` loads the given module. It starts by looking into the `package.loaded` table to determine whether the module is already loaded. If it is, then `require` returns the value stored at `package.loaded[module_name]`. Otherwise, it loads and evaluates the file via a loader.
 
-In our included Lua file, we define a variable origin that we use to store data. This name might lead to problems later on. Suppose we add other types of behavior to our butterflies and use the name "origin" in another situation. Suddenly we cause a name collision. One way to guard against name collisions is to prefix everything in our file:
+The syntax of the filename string provided to `require` is a bit special. Lua replaces '.' characters in the filename string with path separators: '/' on macOS and Linux and '\\' on Windows.
 
-```lua
-local flying_origin
-
-function flying_fly_randomly(radius)
-    ...
-end
-```
-
-This works, but Lua provides a simple and elegant way to organize script code and data: modules.
+Note that it is usually a bad idea to use the global scope to store state and define functions like we did above. You risk naming collisions, exposing the state of the module or introduce coupling between users of the module.
 
 ## Modules
 
-A Lua module is nothing more than a Lua table that we use as a container for our functions and behaviours. Here is the module version of "flying.lua", which also includes a fix to the data-sharing problem we hit earlier:
+To encapsulate data and functions, Lua uses _modules_. A Lua module is a regular Lua table that is used to contain functions and data. The table is declared local not to pollute the global scope:
 
 ```lua
--- The table "M" contains the module.
 local M = {}
 
--- We use a table to store original positions.
--- Note that the module becomes part of all game objects'
--- shared Lua context so we can't just store the origin in
--- a variable straight - it would be overwritten if more than
--- one GO used this module
-M.origins = {}
-
--- Crudely fly to a random position at "radius" distance
--- from the original position
--- This function sends back a "fly_randomly_done" message when it's done.
-function M.fly_randomly(radius)
-    -- Radius is 100 unless specified
-    radius = radius or 100
-    -- We need current object id to index the original position.
-    -- Can't use "."
-    local go_id = go.get_id()
-    -- Store origin position if it's not already stored.
-    if M.origins[go_id] == nil then
-        M.origins[go_id] = go.get_world_position(go_id)
-    end
+-- private
+local message = "Hello world!"
 
-    -- Figure out a random position at max distance
-    -- "radius" from origin
-    local rand_angle = math.random(0, 3.141592 * 2)
-    local rand_radius = math.random(radius)
-    local offset = vmath.rotate(vmath.quat_rotation_z(rand_angle),
-                                vmath.vector3(rand_radius, 0, 0))
-    local rand_pos = M.origins[go_id] + offset
-    -- Set a random duration scaled against the radius to prevent
-    -- too fast animation.
-    local rand_duration = math.random(radius) / 100 + (radius / 200)
-    -- Animate, then send a message back when completed
-    go.animate(".", "position", go.PLAYBACK_ONCE_FORWARD,
-        rand_pos, go.EASING_INOUTSINE, rand_duration, 0.0,
-        function ()
-            msg.post("#", "fly_randomly_done")
-        end)
+function M.hello()
+    print(message)
 end
 
 return M
 ```
 
-The difference is that we create a table, "flying", that we populate with our data (`flying.origins`) and functions (`flying.fly_randomly()`). We end the module by returning the table. To use the module we change the butterfly scripts to:
-
-```lua
-flying = require "modules_example.flying"
-
-function init(self)
-    flying.fly_randomly()
-end
-
-function on_message(self, message_id, message, sender)
-    if message_id == hash("fly_randomly_done") then
-        flying.fly_randomly()
-    end
-end
-```
-
-When requiring an external file, we assign the required script’s return value to a variable:
-
-```lua
-flying = require "modules_example.flying"
-```
-
-Since the module returns the table containing all the module code and data we get that table reference in the variable flying. We are free to name the table arbitrarily so we could just as well write:
+The module can then be used. Again, it is prefered to assign it to a local variable:
 
 ```lua
-banana = require "modules_example.flying"
-
-function init(self)
-    banana.fly_randomly()
-end
-
-function on_message(self, message_id, message, sender)
-    if message_id == hash("fly_randomly_done") then
-        banana.fly_randomly()
-    end
-end
+local m = require "mymodule"
+m.hello() --> "Hello world!"
 ```
 
-This means that we can even use two modules with the same name--we just assign them locally to different variable names.
-
-With the module mechanism we are now fully equipped to encapsulate shared functionality and avoid any name collisions.
-
-## Naming conventions
+## Hot reloading modules
 
-There are many different ways to define the module table, but we recommend using the standard of naming the table containing the public functions and values `M` (See http://lua-users.org/wiki/ModuleDefinition). The use of the name `M` helps, since it prevents mistakes like accidentally shadowing the module table by a function argument with the same name.
+Consider a simple module:
 
 ```lua
---- Module description
--- @module foobar
-local M = {}
-
---- Constant for bar
--- @field BAR
-M.BAR = "bar"
-
-local function private_function()
-end
-
---- If the module needs to retain a non-singleton state it should have a
--- create function that returns an "instance" with the state. This instance can
--- then be passed to the module functions.
--- @return Instance of foobar
-function M.create()
-    local foobar = {
-        foo = "foo"
-    }
-    return foobar
-end
-
---- This function does something.
--- @function do_something
--- @param foobar
--- @return foo
-function M.do_something(foobar)
-    return foobar.foo
-end
-
---- This function does something else.
--- @function do_something_else
--- @param foobar
--- @return foobar
-function M.do_something_else(foobar)
-    return M.do_something(foobar) + M.BAR
-end
-
+-- module.lua
+local M = {} -- creates a new table in the local scope
+M.value = 4711
 return M
 ```
 
-## Allowing monkey patching
-
->   "A monkey patch is a way to extend or modify the run-time code of dynamic languages
->   without altering the original source code." [Wikipedia]
-
-Lua is a dynamic language and as such it is possible to modify all of the builtin modules. This is extremely powerful and very useful, primarily for testing and debugging purposes. Monkey patching easily leads to strong coupling, which is usually a bad idea. However, if you write a module, you should make it possible to monkey patch your custom modules as well. Lua allows you to do things like:
+And a user of the module: 
 
 ```lua
--- mymodule.lua
-local M = {}
-
-M.foo = function()
-    print('this is a public module function')
-end
-
-setmetatable(M, {
-    __newindex = function(m, t)
-        error('The user has tried to add the attribute ' .. t .. ' to the module!')
-    end
-})
-
-return M
+local m = require "module"
+print(m.value) --> "4711" (even if "module.lua" is changed and hot reloaded)
 ```
 
-Tricks like the above are usually not a good idea. You should leave the decision on what to do to your module to the user.
+If you hot reload the module file the code is run again, but nothing happens with `m.value`. Why is that?
 
-## Beware of locals
+First, the table created in "module.lua" is created in local scope and a _reference_ to that table is returned to the user. Reloading "module.lua" evaluates the module code again but that creates a new table in the local scope instead of updating the table `m` refers to.
 
-If you decide to not define modules using the style mentioned above (by defining functions as table fields directly) you should be wary of how you use locals. Here is an example (from the blog [kiki.to](http://kiki.to/blog/2014/04/04/rule-3-allow-monkeypatching/)):
+Secondly, Lua caches required files. The first time a file is required, it is put in the table [`package.loaded`](/ref/package/#package.loaded) so it can be read faster on subrequent requires. You can force a file to be re-read from disk by setting the file's entry to nil: `package.loaded["my_module"] = nil`.
 
-```lua
-local M = {}
+To properly hot reload a module, you need to reload the module, reset the cache and then reload all files that uses the module. This is far from optimal.
 
-local function sum(a, b)
-    return a + b
-end
-
-local function mult(a, b)
-    local result = 0
-    for i=1,b do
-        result = sum(result, a)
-    end
-    return result
-end
-
-M.sum = sum
-M.mult = mult
-
-return M
-```
-
-This is a very simple calculator module. Notice how the module table is assigned its public functions at the end. Also notice how the local `mult()` function uses the local `sum()` function. Doing so might be marginally faster, but it also introduces a subtle issue. If we, for some reason, were to monkey patch the module like this:
+Instead, you might consider a workaround to use _during development_: put the module table in the global scope and have `M` refer to the global table instead of creating a new table each time the file evaluates. Reloading the module then changes the contents of the global table:
 
 ```lua
-local summult = require("summult")
-summult.sum = function(a,b) return 1 end
-print(summult.mult(5,2))
-```
-
-Now, even after being overridden, `summult.mult(5,2)` still returns `10` (while you would expect 1). The problem is that the user changes the `sum()` function on the module table, but internally in `multi()` the local and unmodified function is still used.
+--- module.lua
 
-## Don’t pollute the global scope
-
-This best practice is not specific to modules, but it’s worth reiterating the importance of not using the global scope to store state or define functions. One obvious risk of storing state in the global scope is that you expose the state of the module. Another is the risk of two modules using the same global variables (coupling). Note, though that Defold shares the Lua context only between objects in the same collection, so there is no truly global scope.
-
-It’s a good practice during development to monitor the global table and raise an `error()` whenever the global table is modified.
-
-::: sidenote
-For more info, read the Lua Wiki page http://lua-users.org/wiki/DetectingUndefinedVariables
-:::
-
-This code can be used to guard the global table:
-
-```lua
---- A module for guarding tables from new indices. Typical use is to guard the global scope.
--- Get the latest version from https://gist.github.com/britzl/546d2a7e32a3d75bab45
--- @module superstrict
--- @usage
---
---  -- Defold specific example. Allow the gameobject and gui script lifecycle functions. Also allow assignment of
---  -- facebook and iap modules for dummy implementations on desktop. The whitelist handles pattern matching and in the
---  -- example all functions prefixed with '__' will also be allowed in the global scope
---  local superstrict = require("superstrict")
---  superstrict.lock(_G, { "go", "gui", "msg", "url", "sys", "render", "factory", "particlefx", "physics", "sound", "sprite", "image", "tilemap", "vmath", "matrix4", "vector3", "vector4", "quat", "hash", "hash_to_hex", "hashmd5", "pprint", "iap", "facebook", "push", "http", "json", "spine", "zlib", "init", "final", "update", "on_input", "on_message", "on_reload", "__*" })
---
---  -- this will be allowed
---  __allowed = "abc"
---
---  -- and this
---  facebook = dummy_fb
---
---  -- this is ok
---  function init(self)
---  end
---
---  -- this will throw an error
---  if foo == "bar" then
---  end
---
---  -- this will also throw an error
---  function global_function_meant_to_be_local()
---  end
---
-local M = {}
-
--- mapping between tables and whitelisted names
-local whitelisted_names = {}
-
--- make sure that no one messes with the error function since we need it to communicate illegal access to locked tables
-local _error = error
-
---- Check if a key in a table is whitelisted or not
--- @param t The table to check for a whitelisted name
--- @param n Name of the variable to check
--- @return true if n is whitelisted on t
-local function is_whitelisted(t, n)
-    for _,whitelisted_name in pairs(whitelisted_names[t] or {}) do
-        if n:find(whitelisted_name) then
-            return true
-        end
-    end
-    return false
-end
-
---- Guarded newindex
--- Will check if the specified name is whitelisted for the table. If the name isn't whitelisted
--- an error will be thrown.
--- @param t The table on which a new index is being set
--- @param n Name of the variable to set on the table
--- @param v The value to set
-local function lock_newindex(t, n, v)
-    if is_whitelisted(t, n) then
-        rawset(t, n, v)
-        return
-    end
-
-    _error("Table [" .. tostring(t) .. "] is locked. Attempting to write value to '" .. n .. "'. You must declare '" .. n .. "' as local or added it to the whitelist.", 2)
-end
-
---- Guarded __index
--- Will throw an error if trying to read undefined value
--- @param t The table on which a new index is being set
--- @param n Name of the variable to set on the table
-local function lock_index(t, n)
-    if is_whitelisted(t, n) then
-        return rawget(t, n)
-    end
-
-    _error("Table [" .. tostring(t) .. "] is locked. Attempting to read undefined value '" .. n .. "'.", 2)
-end
-
---- Lock a table. This will prevent the table from being assigned new values (functions and variables)
--- Typical use is to call lock(_G) to guard the global scope from accidental assignments
--- @param t Table to lock
--- @param whitelist List of names that are allowed on the table
-function M.lock(t, whitelist)
-    assert(t, "You must pass a table to lock")
-    whitelisted_names[t] = whitelist or {}
-    local mt = getmetatable(t) or {}
-    mt.__newindex = lock_newindex
-    mt.__index = lock_index
-    setmetatable(t, mt)
-end
-
----
--- Unlock a table
--- @param t Table to unlock
-function M.unlock(t)
-    assert(t, "You must pass a table to unlock")
-    local mt = getmetatable(t) or {}
-    mt.__newindex = rawset
-    mt.__index = rawget
-    setmetatable(t, mt)
-end
+-- Replace with local M = {} when done
+uniquevariable12345 = uniquevariable12345 or {}
+local M = uniquevariable12345
 
+M.value = 4711
 return M
 ```
 
-Modules should also try to provide functions to manipulate internal state, instead of exposing it to the user. If you provide functions to manipulate internal state it becomes trivial to refactor the inner workings of the module without affecting users of the module. This practice of encapsulating state is a common practice in OOP languages, but it applies just as much to Lua module development.
-
-## Stateless or stateful modules?
+## Modules and state
 
 Stateful modules keep an internal state that is shared between all users of the module and can be compared to singletons:
 
@@ -471,135 +135,105 @@ end
 return M
 ```
 
-A stateless module on the other hand doesn’t keep any internal state. Instead it provides a mechanism to externalize the state into a separate table that is local to the module user. Most approaches to stateless modules rely on a constructor function within the module, often called `create()` or `new()`. The constructor function returns a table where state is stored, and depending on the implementation sometimes also the module functions themselves.
-
-## Stateless modules using only a state table
-
-Perhaps the easiest approach is to use a constructor function that returns a new table containing only state. The state is explicitly passed to the module as the first parameter of every function that manipulates the state table.
-
-```lua
-local M = {}
-
-local function private_function(self, bar)
-    return self.public_variable .. bar
-end
-
-function M.public_function(self, bar)
-    return private_function(self, bar)
-end
-
-function M.new(foo)
-    local instance = {
-        public_variable = foo
-    }
-    return instance
-end
-
-return M
-```
-
-You use the module like this:
-
-```lua
-local foobar = require(“foobar”)
-local fb = foobar.new(“foo”)
-print(fb.public_variable)
-print(foobar.public_function(fb, “bar”))
-```
-
-## Stateless modules using metatables
-
-::: sidenote
-_Metatables_ are a powerful feature in Lua. A good tutorial on how they work can be found here: http://nova-fusion.com/2011/06/30/lua-metatables-tutorial/
-:::
-
-Another approach is to use a constructor function that returns a new table with state _and_ the public functions of the module each time it’s called:
-
-```lua
-local M = {}
-
-local function private_function(self, bar)
-    return self.public_variable .. bar
-end
-
-function M:public_function(bar)
-    return private_function(self, bar)
-end
-
-function M.new(foo)
-    local instance = {
-        public_variable = foo
-    }
-    return setmetatable(instance, { __index = M })
-end
-
-return M
-```
-
-You use this module in the following manner:
-
-```lua
-local foobar = require(“foobar”)
-local fb = foobar.new(“foo”)
-print(fb.public_variable)
-print(fb:public_function(“bar”))
-```
-
-::: sidenote
-Note the use of the colon operator when calling and defining functions on the module. An expression like `o:foo(x)` is just another way to write `o.foo(o, x)`, that is, to call `o.foo()` adding `o` as a first extra argument. In a function declaration, a first parameter `self` is added.
-
-Read more here: http://www.lua.org/pil/5.html
-:::
-
-## Stateless modules using closures
-
-A third way to define a module is by using Lua closures (See http://www.lua.org/pil/6.1.html for details). A function returns the instance and the closure contains the instance, private and public data and functions---there is no need to pass the instance as an argument (either explicitly or implicitly using the colon operator) like when using metatables. This method is also somewhat faster than using metatables since function calls does not need to go through the `__index` metamethods. One drawback is that each closure contains its own copy of the methods so memory consumption is higher. Another is that it's not possible to monkey-patch the instance methods in a clean way.
-
-```lua
-local M = {}
-
-function M.new(foo)
-    local instance = {
-        public_variable = foo
-    }
-
-    local private_variable = ""
-
-    local private_function = function(bar)
-        return instance.public_variable .. private_variable .. bar
-    end
-
-    instance.public_function = function(bar)
-        return private_function(bar)
-    end
-
-    return instance
-end
-
-return M
-```
-
-Use the module in the following manner:
-
-```lua
-local foobar = require(“foobar”)
-local fb = foobar.new(“foo”)
-print(fb.public_variable)
-print(fb.public_function(“bar”))
-```
-
-## Modules should behave expectedly
-
-Modules are primarily intended to simplify reuse and to encapsulate behavior. When writing a module, it is important to design the module and name its functions in such a way that the expected behavior can be inferred simply by looking at module, function and argument names.
-
-If a function in the module account is named `login(username, password)` the expected behavior is that the function should perform a login to an account using the specified username and password---and nothing else.
-
-## Document the module
-
-::: sidenote
-Details on the LDoc documentation standard can be found here: https://github.com/stevedonovan/LDoc
-:::
-
-When documenting a module or function, remember to write documentation only when it adds information that can’t be inferred from function and argument names. In many cases short, well named functions and well named function arguments are enough to infer how the module works, what to use and what to expect from a function call. Document return values, preconditions and examples of usage. Write documentation using the LDoc standard.
-
-
+A stateless module on the other hand doesn’t keep any internal state. Instead it provides a mechanism to externalize the state into a separate table that is local to the module user. Here are a few different ways to implement this:
+
+Using a state table
+: Perhaps the easiest approach is to use a constructor function that returns a new table containing only state. The state is explicitly passed to the module as the first parameter of every function that manipulates the state table.
+
+  ```lua
+  local M = {}
+  
+  function M.alter_state(the_state, v)
+      the_state.value = the_state.value + v
+  end
+  
+  function M.get_state(the_state)
+      return the_state.value
+  end
+  
+  function M.new(v)
+      local state = {
+          value = v
+      }
+      return state
+  end
+  
+  return M
+  ```
+  
+  Use the module like this:
+  
+  ```lua
+  local m = require "main.mymodule"
+  local my_state = m.new(42)
+  m.alter_state(my_state, 1)
+  print(m.get_state(my_state)) --> 43
+  ```
+
+Using metatables
+: Another approach is to use a constructor function that returns a new table with state and the public functions of the module each time it’s called:
+
+  ```lua
+  local M = {}
+  
+  function M:alter_state(v)
+      -- self is added as first argument when using : notation
+      self.value = self.value + v
+  end
+  
+  function M:get_state()
+      return self.value
+  end
+  
+  function M.new(v)
+      local state = {
+          value = v
+      }
+      return setmetatable(state, { __index = M })
+  end
+  
+  return M
+  ```
+
+  Use the module like this:
+
+  ```lua
+  local m = require "main.mymodule"
+  local my_state = m.new(42)
+  my_state:alter_state(1) -- "my_state" is added as first argument when using : notation
+  print(my_state:get_state()) --> 43
+  ```
+
+Using closures
+:  A third way is to return a closure containing all state and functions. There is no need to pass the instance as an argument (either explicitly or implicitly using the colon operator) like when using metatables. This method is also somewhat faster than using metatables since function calls does not need to go through the `__index` metamethods but each closure contains its own copy of the methods so memory consumption is higher.
+
+  ```lua
+  local M = {}
+  
+  function M.new(v)
+      local state = {
+          value = v
+      }
+  
+      state.alter_state = function(v)
+          state.value = state.value + v
+      end
+  
+      state.get_state = function()
+          return state.value
+      end
+  
+      return state
+  end
+  
+  return M
+  ```
+
+  Use the module like this:
+
+  ```lua
+  local m = require "main.mymodule"
+  local my_state = m.new(42)
+  my_state.alter_state(1)
+  print(my_state.get_state()) 
+  ```

+ 114 - 0
docs/en/manuals/profiling.md

@@ -0,0 +1,114 @@
+---
+title: Profiling in Defold
+brief: This manual explains the profiling facilities present in Defold.
+---
+
+# Profiling
+
+Defold includes a set of profiling tools that are integrated with the engine and the build pipeline. These are designed to help find problems with performance and memory usage. The built in profilers are available on debug builds only.
+
+## The runtime visual profiler
+
+Debug builds feature a runtime visual profiler that displays live information rendered overlayed on top of the running application. It is turned on and off my sending a message named "toggle_profile" to the "system" socket:
+
+```lua
+function on_reload(self)
+    -- Toggle the visual profiler on hot reload.
+    msg.post("@system:", "toggle_profile")
+end
+```
+
+![Visual profiler](images/profiling/visual_profiler.png)
+
+## The web profiler
+
+While running a debug build of the game, an interactive web-based profiler can be accessed through a browser. It allows you to sample your game over a series of frames and then analyze each frame in detail.
+
+To access the profiler:
+
+1. Start your game on your target device.
+2. Open a web browser and point it to `http://<device IP>:8002` where `<device IP>` is the IP address of the device. You can find the IP numbers of your target devices in the <kbd>Project ▸ Target</kbd> menu. If you are running your game on your desktop computer, http://localhost:8002 will bring up the profiler.
+
+![Web profiler](images/profiling/webprofiler_page.png)
+
+The profiler is divided into 4 sections that all give different views into the current sample data. To update the sample data, press the *Capture* button at the top.
+
+Frames overview
+: The frames overview plots the currently sampled 20 frames side by side. The height of each bar shows the time spent in the frame. The number on the left hand side shows the max time spent in a frame in the current sample data.
+
+  ![Frames overview](images/profiling/webprofiler_frames_overview.png)
+
+  Below the frames overview is a detailed frame data view.
+
+  Click on a frame bar in the overview to show the data for that specific frame in the data view.
+
+Frame data
+: The frame data view is a table where all data for the currently selected frame is broken down into detail. You can view how many milliseconds are spent in each engine scope (to the left) and also see sample points within the scopes (middle column). On the right hand side is a table of counters. They make it is easy to, for instance, track the number of draw calls required for each frame in the sample data.
+
+  ![Frame data](images/profiling/webprofiler_frame_data.png)
+
+  Ticking the checkbox associated with a sample point or counter adds that data to the plot below.
+
+Frames plot
+: The frames plot view displays a plot over all sampled frames with the data you have selected in the frame data table above the plot. The plot shows frame number on the X axis and time (in milliseconds) or counts on the Y axis. Each selected data point is drawn in the color specified in the frame data table.
+
+  ![Frames plot](images/profiling/webprofiler_frames_plot.png)
+
+Frame time chart
+:  The frame time chart breaks the frame down visually making it easy to inspect where the engine spends its time during the selected frame.
+
+  ![Frame timechart](images/profiling/webprofiler_frame_timechart.png)
+
+## Build reports
+
+When bundling your game there is an option to create a build report. This is very useful to get a grip on the size of all the assets that are part of your game bundle. Simply check the *Generate build report* checkbox when bundling the game.
+
+![build report](images/profiling/build_report.png){srcset="images/profiling/[email protected] 2x"}
+
+The builder will produce a file called "report.html" alongside the game bundle. Open the file in a web browser to inspect the report:
+
+![build report](images/profiling/build_report_html.png){srcset="images/profiling/[email protected] 2x"}
+
+The *Overview* gives an over all visual breakdown of the project size based on resource type.
+
+*Resources* shows a detailed list of resources that you can sort based on size, compression ratio, encryption, type and directory name. Use the "search" field to filter the resource entries displayed.
+
+The *Structure* section shows sizes based on how resources are organized in the project file structure. Entries are color coded from green (light) to blue (heavy) according to the relative size of the file and directory content.
+
+## External tools
+
+In addition to the built in tools, there is a wide range of free high quality tracing and profiling tools available. Here is a selection:
+
+ProFi (Lua)
+: We do not ship any built in Lua profiler but there are external libraries that are easy enough to use. To find where your scripts spend time, either insert time measures in your code yourself, or use a Lua profiling library like ProFi.
+
+  https://github.com/jgrahamc/ProFi
+
+  Note that pure Lua profilers add quite a lot of overhead with each hook they install. For this reason you should be a bit wary of the timing profiles you get from such a tool. Counting profiles are accurate enough though.
+
+Instruments (macOS and iOS)
+: This is a performance analyzer and visualizer that is part of Xcode. It allows you to trace and inspect the behavior of one or more apps or processes, examine device specific features (like Wi-Fi and Bluetooth) and much more.
+
+  ![instruments](images/profiling/instruments.png){srcset="images/profiling/[email protected] 2x"}
+
+OpenGL profiler (macOS)
+: Part of the package "Additional Tools for Xcode" that you can download from Apple (select <kbd>Xcode ▸ Open Developer Tool ▸ More Developer Tools...</kbd> in the Xcode menu).
+
+  This tool allows you to inspect a running Defold application and see how it uses OpenGL. It allows you to do traces of OpenGL function calls, set breakpoints on OpenGL functions, investigate application resources (textures, programs, shaders etc), look at buffer contents, and check other aspects of the OpenGL state.
+
+  ![opengl profiler](images/profiling/opengl.png){srcset="images/profiling/[email protected] 2x"}
+
+Android Profiler (Android)
+: https://developer.android.com/studio/profile/android-profiler.html
+
+  A set of profiling tools that captures realtime data of your game's CPU, memory, and network activity. You can perform sample-based method tracing of code execution, capture heap dumps, view memory allocations, and inspect the details of network-transmitted files. Using the tool requires that you set `android:debuggable="true"` in "AndroidManifest.xml".
+
+  ![android profiler](images/profiling/android_profiler.png)
+
+Graphics API Debugger (Android)
+: https://github.com/google/gapid
+
+  This is a collection of tools that allows you to inspect, tweak and replay calls from an application to a graphics driver. To use the tool requires that you set `android:debuggable="true"` in "AndroidManifest.xml".
+
+  ![graphics api debugger](images/profiling/gapid.png)
+

+ 99 - 0
docs/en/manuals/zerobrane.md

@@ -0,0 +1,99 @@
+---
+title: Debugging with ZeroBrane Studio
+brief: This manual explains how to use ZeroBrane Studio to debug Lua code in Defold.
+---
+
+# Debugging Lua scripts with ZeroBrane Studio
+
+Defold contains a built-in debugger, but it is also possible to run the free and open-source Lua IDE _ZeroBrane Studio_ as an external debugger. ZeroBrane Studio needs to be installed in order to use the debugging features. The program is cross-platform and runs on both OSX and Windows.
+
+Download "ZeroBrane Studio" from http://studio.zerobrane.com
+
+## ZeroBrane configuration
+
+In order for ZeroBrane to find the files in your project, you need to point it to the location of your Defold project directory. A convenient way of finding this out is by using the <kbd>Show in Desktop</kbd> option on a file the root of your Defold project.
+
+1. Right click on *game.project*
+2. Choose <kbd>Show in Desktop</kbd>
+
+![Show in Finder](images/zerobrane/show_in_desktop.png){ srcset="images/zerobrane/[email protected] 2x" }
+
+## To set up ZeroBrane
+
+To set up ZeroBrane, select <kbd>Project ▸ Project Directory ▸ Choose...</kbd>:
+
+![Set up](images/zerobrane/setup.png)
+
+Once this has been set up to match the current Defold project directory, it should be possible to see the directory tree of the Defold project in ZeroBrane, and to navigate and open the files.
+
+Other recommended, but not necessary configuration changes can be found further down in the document.
+
+## Starting the debugging server
+
+Before starting a debugging session, the ZeroBrane built-in debugging server needs to be started. The menu option for starting it can be found under the <kbd>Project</kbd> menu. Just select <kbd>Project ▸ Start Debugger Server</kbd>:
+
+![Start debugger](images/zerobrane/startdebug.png)
+
+## Connecting your application to the debugger
+
+Debugging can be started at any point in the lifetime of the Defold application, but needs to be actively initiated from Lua script. The Lua code to start a debugging session looks like this:
+
+::: sidenote
+If your game exits when `dbg.start()` is called, it might be because ZeroBrane has detected a problem and sends the exit command to the game. For some reason, ZeroBrane needs a file opened to start the debug session, otherwise it will output:
+"Can't start debugging without an opened file or with the current file not being saved 'untitled.lua')."
+In ZeroBrane, open the file you added `dbg.start()` to fix this error.
+:::
+
+```lua
+dbg = require "builtins.scripts.mobdebug"
+dbg.start()
+```
+
+By inserting the above code into the application, it will connect to ZeroBrane’s debugging server (through "localhost", by default) and pause at the next statement to be executed.
+
+```txt
+Debugger server started at localhost:8172.
+Mapped remote request for '/' to '/Users/my_user/Documents/Projects/Defold_project/'.
+Debugging session started in '/Users/my_user/Documents/Projects/Defold_project'.
+```
+
+Now it is possible to use the debugging features available in ZeroBrane; you can step, inspect, add and remove breakpoints etc.
+
+::: sidenote
+The debugging will only be enabled for the lua context from where debugging is initiated. Enabling "shared_state" in game.project means you can debug your whole application no matter where you started.
+:::
+
+![Stepping](images/zerobrane/code.png)
+
+Should the connection attempt fail (possibly because the debugging server is not running), your application will continue to run as normal after the connection attempt has been made.
+
+## Remote debugging
+
+As debugging happens over regular network connections (TCP), this allows for debugging remotely. This means it is possible to debug your application while it is running on a mobile device.
+
+The only change needed is to the command which starts the debugging. By default, `start()` will try to connect to localhost, but for remote debugging, we need to manually specify the address to ZeroBrane’s debugging server, like this:
+
+```lua
+dbg = require "builtins.scripts.mobdebug"
+dbg.start("192.168.5.101")
+```
+
+This also means it is important to make sure to have network connectivity from the remote device, and that any firewalls or similar software allows TCP connections through on port 8172. Otherwise the application might stall when launching when it attempts to make the connection to your debugging server.
+
+## Other recommended ZeroBrane setting
+
+It is possible to make ZeroBrane automatically open Lua script files during debugging. This makes it possible to step into functions in other source files without having to open them manually.
+
+The first step is to access the editor configuration file. It is recommended that you change the user version of the file.
+
+- Select <kbd>Edit ▸ Preferences ▸ Settings: User</kbd>
+- Add the following to the configuration file:
+
+  ```txt
+  - to automatically open files requested during debugging
+  editor.autoactivate = true
+  ```
+
+- Restart ZeroBrane
+
+![Other recommended settings](images/zerobrane/otherrecommended.png)

+ 9 - 2
gulpfile.js

@@ -46,7 +46,9 @@ md = new markdown({
       try {
         var hl = hljs.highlight(lang, str).value;
         // Callouts hack!
-        return hl.replace(/(?:--|\/\/|#) &lt;([0-9]+)&gt;/g, '<span class="callout" data-pseudo-content="$1"></span>');
+        // replaces "-- [1]", "// [1]" and "-- <1>" and "// <1>" with a span
+        var exp = /(?:--|\/\/|#) (?:\[|&lt;)([0-9]+)(?:\]|&gt;)/g;
+        return hl.replace(exp, '<span class="callout" data-pseudo-content="$1"></span>');
       } catch (__) {}
     }
     return ''; // use external default escaping
@@ -106,9 +108,14 @@ md.renderer.rules.image = function (tokens, idx, options, env, self) {
     var token = tokens[idx];
 
     if('imgurl' in env) {
-        // Rewrite src
+        // Rewrite src and srcset
         var src = token.attrs[token.attrIndex('src')][1];
         token.attrs[token.attrIndex('src')][1] = env.imgurl + '/' + src;
+
+        if(token.attrs[token.attrIndex('srcset')]) {
+          var srcset = token.attrs[token.attrIndex('srcset')][1];
+          token.attrs[token.attrIndex('srcset')][1] = env.imgurl + '/' + srcset;
+        }
     }
     // Set alt attribute
     token.attrs[token.attrIndex('alt')][1] = self.renderInlineAsText(token.children, options, env);