# Defold Documentation > Defold is a free game engine with free source code access. It's designed for creating 2D and 3D games across multiple platforms, including mobile, desktop, web, and consoles. This document contains [Defold's official documentation](https://defold.com/manuals/) in a single-file easy-to-search form. If you find any issues, please report them [as a GitHub issue](https://github.com/defold/doc/issues), and contributions are very welcome in the form of [pull requests](https://github.com/defold/doc/pulls). ## Manuals ### Getting Started - [Introduction](#manuals:introduction) - [Installing Defold](#manuals:install) - [Glossary](#manuals:glossary) - [Defold for Unity users](#manuals:unity) - [Defold for Flash users](#manuals:flash) - [Getting help](#manuals:getting-help) ### Project Setup - [Creating a project](#manuals:project-setup) - [Project settings](#manuals:project-settings) - [Sharing projects](#manuals:libraries) - [Ignoring files](#manuals:project-defignore) ### Editor - [Overview](#manuals:editor) - [Scene Editing](#manuals:scene-editing) - [Code editor](#manuals:writing-code) - [Custom project templates](#manuals:editor-templates) - [Editor scripts](#manuals:editor-scripts) - [Editor scripts: UI](#manuals:editor-scripts-ui) - [Debugger](#manuals:debugging-game-logic) - [Preferences](#manuals:editor-preferences) - [Refactoring](#manuals:refactoring) - [Styling](#manuals:editor-styling) ### Core Concepts - [Building blocks](#manuals:building-blocks) - [Addressing](#manuals:addressing) - [Message passing](#manuals:message-passing) - [Application lifecycle](#manuals:application-lifecycle) ### Assets and Resources - [Importing assets](#manuals:importing-assets) - [Caching assets](#manuals:caching-assets) - [Importing 2D graphics](#manuals:importing-graphics) - [Importing 3D models](#manuals:importing-models) - [Adapting to different screen sizes](#manuals:adapting-graphics-to-screen-size) - [Live update](#manuals:live-update) - [Atlas](#manuals:atlas) - [Buffer](#manuals:buffer) - [Font](#manuals:font) - [Resource management](#manuals:resource) - [Tile source](#manuals:tilesource) - [Texture filtering](#manuals:texture-filtering) - [Texture compression](#manuals:texture-profiles) ### Animations - [Overview](#manuals:animation) - [Flipbook Animation](#manuals:flipbook-animation) - [Model animation](#manuals:model-animation) - [Property animation (tweens)](#manuals:property-animation) - [Rive animation](https://defold.com/extension-rive) - [Spine animation](https://defold.com/extension-spine#playing-animations) ### Components - [Overview](#manuals:components) - [Collection factory](#manuals:collection-factory) - [Collection proxy](#manuals:collection-proxy) - [Collision object](#manuals:physics-objects) - [Camera](#manuals:camera) - [Factory](#manuals:factory) - [Label](#manuals:label) - [Mesh](#manuals:mesh) - [Model](#manuals:model) - [Particle FX](#manuals:particlefx) - [Rive](https://defold.com/extension-rive/#creating-rive-model-components) - [Sound](#manuals:sound) - [Spine](https://defold.com/extension-spine#creating-spine-model-components) - [Sprite](#manuals:sprite) - [Tilemap](#manuals:tilemap) ### GUI - [GUI overview](#manuals:gui) - [Box nodes](#manuals:gui-box) - [Text nodes](#manuals:gui-text) - [Pie nodes](#manuals:gui-pie) - [Spine nodes](https://defold.com/extension-spine#creating-spine-gui-nodes) - [ParticleFX nodes](#manuals:gui-particlefx) - [Template nodes](#manuals:gui-template) - [Scripts](#manuals:gui-script) - [Clipping](#manuals:gui-clipping) - [Layouts](#manuals:gui-layouts) ### Physics - [Physics overview](#manuals:physics) - [Collision objects](#manuals:physics-objects) - [Collision shapes](#manuals:physics-shapes) - [Collision groups](#manuals:physics-groups) - [Collision messages](#manuals:physics-messages) - [Collision events listener](#manuals:physics-events) - [Resolving collisions](#manuals:physics-resolving-collisions) - [Ray casts](#manuals:physics-ray-casts) - [Joints and constraints](#manuals:physics-joints) ### Sound - [Sound](#manuals:sound) - [Sound Streaming](#manuals:sound-streaming) - [FMOD](https://defold.com/assets/fmod/) ### Input - [Overview](#manuals:input) - [Key and text input](#manuals:input-key-and-text) - [Mouse and touch](#manuals:input-mouse-and-touch) - [Gamepads](#manuals:input-gamepads) ### Game logic - [Scripts](#manuals:script) - [Properties](#manuals:properties) - [Script properties](#manuals:script-properties) - [Lua in Defold](#manuals:lua) - [Source code obfuscation](#manuals:application-security) - [Modules](#manuals:modules) - [Debugging](#manuals:debugging-game-logic) - [Writing code](#manuals:writing-code) ### Files - [Working with files](#manuals:file-access) ### Network Connections - [Overview](#manuals:networking) - [HTTP Requests](#manuals:http-requests) - [Socket connections](#manuals:socket-connections) - [WebSocket connections](https://defold.com/extension-websocket) - [Online services](#manuals:online-services) ### Rendering - [Render](#manuals:render) - [Material](#manuals:material) - [Compute](#manuals:compute) - [Shader](#manuals:shader) - [Texture filtering](#manuals:texture-filtering) - [Physically Based Rendering](#manuals:physically-based-rendering) ### Workflow - [Application security](#manuals:application-security) - [Bundling an application](#manuals:bundling) - [Caching assets](#manuals:caching-assets) - [Command line tools](#manuals:bob) - [Hot reloading](#manuals:hot-reload) - [Porting guidelines](#manuals:porting-guidelines) - [Refactoring](#manuals:refactoring) - [The mobile dev app](#manuals:dev-app) - [Version control](#manuals:version-control) - [Writing code](#manuals:writing-code) - [Working offline](#manuals:working-offline) ### Debugging - [Debugging game logic](#manuals:debugging-game-logic) - [Debugging native code](#manuals:debugging-native-code) - [Debugging native code on Android](#manuals:debugging-native-code-android) - [Debugging native code on iOS](#manuals:debugging-native-code-ios) - [Reading game and system logs](#manuals:debugging-game-and-system-logs) ### Optimization - [Optimizing an application](#manuals:optimization) - [Optimize game size](#manuals:optimization-size) - [Optimize runtime performance](#manuals:optimization-speed) - [Optimize battery usage](#manuals:optimization-battery) - [Optimize memory usage](#manuals:optimization-memory) - [Profiling](#manuals:profiling) ### Monetization - [Ads](#manuals:ads) - [In-app purchases](https://defold.com/extension-iap) - [Xsolla](https://defold.com/extension-xsolla) ### Android - [Introduction](#manuals:android) - [Advertising Info](https://defold.com/extension-adinfo) - [AdMob ads](https://defold.com/extension-admob) - [Android Device Performance Framework](https://defold.com/extension-adpf) - [App review and ratings](https://defold.com/extension-review) - [Camera](https://defold.com/extension-camera) - [Facebook](https://defold.com/extension-facebook) - [Firebase Analytics](https://defold.com/extension-firebase-analytics) - [Firebase Remote Config](https://defold.com/extension-firebase-remoteconfig) - [Google Play Game Services](https://defold.com/extension-gpgs) - [Google Play Instant](https://defold.com/extension-googleplayinstant) - [Inter-app communication](#manuals:iac) - [IronSource ad mediation](https://defold.com/extension-ironsource) - [Push notifications](https://defold.com/extension-push) - [Play Asset Delivery](https://defold.com/extension-pad/) - [Safe Area](https://defold.com/extension-safearea) - [Webview](https://defold.com/extension-webview) - [The mobile dev app](#manuals:dev-app) ### iOS - [Introduction](#manuals:ios) - [Advertising Info](https://defold.com/extension-adinfo) - [AdMob ads](https://defold.com/extension-admob) - [App review and ratings](https://defold.com/extension-review) - [Camera](https://defold.com/extension-camera) - [Facebook](https://defold.com/extension-facebook) - [Firebase Analytics](https://defold.com/extension-firebase-analytics) - [Firebase Remote Config](https://defold.com/extension-firebase-remoteconfig) - [Inter-app communication](#manuals:iac) - [IronSource ad mediation](https://defold.com/extension-ironsource) - [Push notifications](https://defold.com/extension-push) - [Safe Area](https://defold.com/extension-safearea) - [Webview](https://defold.com/extension-webview) - [The mobile dev app](#manuals:dev-app) ### Consoles - [Nintendo Switch](#manuals:nintendo-switch) - [PlayStation®4](#manuals:sony-playstation) - [PlayStation®5](#manuals:sony-playstation) - [Microsoft Xbox](#manuals:microsoft-xbox) ### HTML5 - [Introduction](#manuals:html5) - [CrazyGames](https://defold.com/extension-crazygames) - [Facebook](https://defold.com/extension-facebook) - [Facebook Instant Games](https://defold.com/extension-fbinstant) - [Poki](https://defold.com/extension-poki-sdk) ### Desktop - [Linux](#manuals:linux) - [macOS](#manuals:macos) - [Windows](#manuals:windows) ### Engine extensions - [Introduction](#manuals:extensions) - [Defold SDK](#manuals:extensions-defold-sdk) - [Gradle dependencies](#manuals:extensions-gradle) - [Cocoapod dependencies](#manuals:extensions-cocoapods) - [Adding auto-complete definition](#manuals:extensions-script-api) - [Best Practices](#manuals:extensions-best-practices) - [Debugging](#manuals:debugging-native-code) - [Extension Manifests](#manuals:extensions-ext-manifests) - [App Manifests](#manuals:app-manifest) - [Manifest Merging](#manuals:extensions-manifest-merge-tool) - [The Lua C API (external)](https://www.lua.org/pil/contents.html#P4) - [Setup local build server](#manuals:extender-local-setup) - [Available Docker images to run Extender](#manuals:extender-docker-images) # Defold API Reference This document contains the Defold API reference, grouped by language. ## C++ APIs - [dmDDF (Ddf)](#apis:engine-ddf-src-dmsdk-ddf-ddf-h) - DDF (Defold Data Format) API documentation - [dmAndroid (Android)](#apis:engine-dlib-src-dmsdk-dlib-android-h) - Android utility functions - [Array](#apis:engine-dlib-src-dmsdk-dlib-array-h) - Templatized array with bounds checking - [dmBuffer (Buffer)](#apis:engine-dlib-src-dmsdk-dlib-buffer-h) - Buffer API for data buffers as the main way to communicate between systems - [dmConditionVariable (Condition Variable)](#apis:engine-dlib-src-dmsdk-dlib-condition_variable-h) - API for platform independent mutex synchronization primitive - [dmConfigFile (ConfigFile)](#apis:engine-dlib-src-dmsdk-dlib-configfile_gen-hpp) - Configuration file access functions - [dmConnectionPool (Connection Pool)](#apis:engine-dlib-src-dmsdk-dlib-connection_pool-h) - Connection pool - [dmCrypt (Crypt)](#apis:engine-dlib-src-dmsdk-dlib-crypt-h) - Various hash and encode/decode functions - [dmDoubleLinkedList (Double linked list structs and functions)](#apis:engine-dlib-src-dmsdk-dlib-double_linked_list-h) - Double linked list structs and functions - [dmFileDescriptor (FileDescriptor)](#apis:engine-dlib-src-dmsdk-dlib-file_descriptor-h) - File Descriptor functions - [Hashtable](#apis:engine-dlib-src-dmsdk-dlib-hashtable-h) - Hash table - [dmHttpClient (Http Client)](#apis:engine-dlib-src-dmsdk-dlib-http_client-h) - Http client functions - [dmImage (Image)](#apis:engine-dlib-src-dmsdk-dlib-image-h) - Image API functions - [dmIntersection (Intersection structs and functions)](#apis:engine-dlib-src-dmsdk-dlib-intersection-h) - Intersection math structs and functions - [Log](#apis:engine-dlib-src-dmsdk-dlib-log-h) - Logging functions - [dmMath (Math)](#apis:engine-dlib-src-dmsdk-dlib-math-h) - Math functions - [dmMemory (Memory)](#apis:engine-dlib-src-dmsdk-dlib-memory-h) - Memory allocation functions - [dmMessage (Message)](#apis:engine-dlib-src-dmsdk-dlib-message-h) - Api for sending messages - [dmMutex (Mutex)](#apis:engine-dlib-src-dmsdk-dlib-mutex-h) - API for platform independent mutex synchronization primitive - [ObjectPool](#apis:engine-dlib-src-dmsdk-dlib-object_pool-h) - Object Pool API documentation - [dmProfile (Profile)](#apis:engine-dlib-src-dmsdk-dlib-profile-h) - Profiling macros - [SharedLibrary (Shared Library)](#apis:engine-dlib-src-dmsdk-dlib-shared_library-h) - Utility functions for shared library export/import - [dmSocket (Socket)](#apis:engine-dlib-src-dmsdk-dlib-socket-h) - Socket functions - [dmSpinlock (Spinlock)](#apis:engine-dlib-src-dmsdk-dlib-spinlock-h) - API for platform independent spinlock synchronization primitive - [dmSSLSocket (SSLSocket)](#apis:engine-dlib-src-dmsdk-dlib-sslsocket-h) - Secure socket functions - [dmStaticAssert (Static Assert)](#apis:engine-dlib-src-dmsdk-dlib-static_assert-h) - ```cpp void test() { DM_STATIC_ASSERT(sizeof(int) == 4, Invalid_int_size); } ``` - [dmSys (Sys)](#apis:engine-dlib-src-dmsdk-dlib-sys-h) - Sys allocation functions - [dmThread (Thread)](#apis:engine-dlib-src-dmsdk-dlib-thread-h) - Thread functions - [dmTime (Time)](#apis:engine-dlib-src-dmsdk-dlib-time-h) - Time functions - [dmTransform (Transform)](#apis:engine-dlib-src-dmsdk-dlib-transform-h) - Api for transforms with rotation, scale and translation - [dmURI (URI)](#apis:engine-dlib-src-dmsdk-dlib-uri-h) - URI functions - [dmUtf8 (Utf8)](#apis:engine-dlib-src-dmsdk-dlib-utf8-h) - Utf8 API documentation - [dmVMath (Vector Math)](#apis:engine-dlib-src-dmsdk-dlib-vmath-h) - Vector Math functions - [dmWebServer (WebServer)](#apis:engine-dlib-src-dmsdk-dlib-webserver-h) - Simple high-level single-threaded Web server based on dmHttpServer The web-server has a handler concept similar to servlets in Java - [dmEngine (Engine)](#apis:engine-engine-src-dmsdk-engine-extension-hpp) - SDK Engine extension API documentation - [engine (Engine runtime)](#apis:engine-engine-src-engine_doc-h) - Engine runtime documentation - [dmExtension (Extension)](#apis:engine-extension-src-dmsdk-extension-extension_gen-hpp) - Functions for creating and controlling engine native extension libraries - [dmGameObject (Component)](#apis:engine-gameobject-src-dmsdk-gameobject-component-h) - Api for manipulating game object components (WIP) - [dmGameObject (Gameobject)](#apis:engine-gameobject-src-dmsdk-gameobject-gameobject-h) - API for manipulating game objects - [dmGameObject (PropertyContainer)](#apis:engine-gameobject-src-dmsdk-gameobject-gameobject_props-h) - API for game object property container - [dmGameObject (Script)](#apis:engine-gameobject-src-dmsdk-gameobject-script-h) - GameObject script API documentation - [dmGameSystem (Collection factory)](#apis:engine-gamesys-src-dmsdk-gamesys-components-comp_collection_factory-h) - API for spawning collections from a collection factory component - [dmGameSystem (Factory)](#apis:engine-gamesys-src-dmsdk-gamesys-components-comp_factory-h) - API for spawning gameobject instances from a factory component - [dmGameSystem (GameSystem GUI Component)](#apis:engine-gamesys-src-dmsdk-gamesys-components-comp_gui-h) - Per-property registration functions for GUI component extensions - [dmGameSystem (Model)](#apis:engine-gamesys-src-dmsdk-gamesys-components-comp_model-h) - API for interacting with model components - [dmGameSystem (GameSystem Gui)](#apis:engine-gamesys-src-dmsdk-gamesys-gui-h) - Built-in scripting functions - [dmGameSystem (Property)](#apis:engine-gamesys-src-dmsdk-gamesys-property-h) - Property functions - [dmGameSystem (Component Render Constants)](#apis:engine-gamesys-src-dmsdk-gamesys-render_constants-h) - Api for setting and updating component render constants - [dmGameSystem (Data Resource)](#apis:engine-gamesys-src-dmsdk-gamesys-resources-res_data-h) - Helper types and accessors for the data resource type (` - [dmGameSystem (Font Resource)](#apis:engine-gamesys-src-dmsdk-gamesys-resources-res_font-h) - Font resource functions - [dmGameSystem (Light Resource)](#apis:engine-gamesys-src-dmsdk-gamesys-resources-res_light-h) - Helper types and accessors for the light resource type (` - [dmScript (Script)](#apis:engine-gamesys-src-dmsdk-gamesys-script-h) - Built-in scripting functions - [dmGraphics (Graphics)](#apis:engine-graphics-src-dmsdk-graphics-graphics-h) - Graphics API - [dmGraphics (Graphics)](#apis:engine-graphics-src-dmsdk-graphics-graphics_native-h) - Platform specific native graphics functions - [dmGraphics (Graphics OpenGL)](#apis:engine-graphics-src-dmsdk-graphics-graphics_opengl-h) - Graphics OpenGL API - [dmGraphics (Graphics Vulkan)](#apis:engine-graphics-src-dmsdk-graphics-graphics_vulkan-h) - Graphics Vulkan API - [dmGui (Gui)](#apis:engine-gui-src-dmsdk-gui-gui-h) - Defold GUI system - [dmHid (Hid)](#apis:engine-hid-src-dmsdk-hid-hid-h) - Used to add input to the engine - [dmPhysics (Physics)](#apis:engine-physics-src-dmsdk-physics-physics-h) - Physics related structs and functions - [dmRender (Render)](#apis:engine-render-src-dmsdk-render-render-h) - Api for render specific data - [dmResource (Resource)](#apis:engine-resource-src-dmsdk-resource-resource-hpp) - Functions for managing resource and resource types - [dmResource (Resource)](#apis:engine-resource-src-dmsdk-resource-resource_gen-hpp) - Functions for managing resource types - [dmScript (Script)](#apis:engine-script-src-dmsdk-script-script-h) - Built-in scripting functions - [dmSound (Sound)](#apis:engine-sound-src-dmsdk-sound-sound-h) - Functions for controlling the engine sound mixer from native extensions ## Lua APIs - [b2d](#apis:b2d-lua) - Functions for interacting with Box2D - [b2d.body](#apis:b2d.body-lua) - Functions for interacting with Box2D bodies - [base (Base)](#apis:base-lua) - Documentation for the Lua base standard library - [bit (BitOp)](#apis:bit-lua) - [Lua BitOp](http://bitop - [buffer (Buffer)](#apis:buffer-lua) - Functions for manipulating buffers and streams - [builtins (Built-ins)](#apis:builtins-lua) - Built-in scripting functions - [camera (Camera)](#apis:camera-lua) - Messages to control camera components and camera focus - [collectionfactory (Collection factory)](#apis:collectionfactory-lua) - Functions for controlling collection factory components which are used to dynamically spawn collections into the runtime - [collectionproxy (Collection proxy)](#apis:collectionproxy-lua) - Messages for controlling and interacting with collection proxies which are used to dynamically load collections into the runtime - [coroutine (Coroutine)](#apis:coroutine-lua) - Documentation for the Lua coroutine standard library - [crash (Crash)](#apis:crash-lua) - Native crash logging functions and constants - [debug (Debug)](#apis:debug-lua) - Documentation for the Lua debug standard library - [editor (Editor)](#apis:editor-lua) - Editor scripting documentation - [factory (Factory)](#apis:factory-lua) - Functions for controlling factory components which are used to dynamically spawn game objects into the runtime - [font (Font)](#apis:font-lua) - Functions, messages and properties used to manipulate font resources - [go (Game object)](#apis:go-lua) - Game object API documentation - [graphics (Graphics)](#apis:graphics-lua) - Graphics functions and constants - [gui (GUI)](#apis:gui-lua) - GUI API documentation - [html5 (HTML5)](#apis:html5-lua) - HTML5 platform specific functions - [http (HTTP)](#apis:http-lua) - Functions for performing HTTP and HTTPS requests - [image (Image)](#apis:image-lua) - Functions for creating image objects - [io (Io)](#apis:io-lua) - Documentation for the Lua io standard library - [json (JSON)](#apis:json-lua) - Manipulation of JSON data strings - [label (Label)](#apis:label-lua) - Functions to manipulate a label component - [liveupdate (LiveUpdate)](#apis:liveupdate-lua) - Functions and constants to access resources - [math (Math)](#apis:math-lua) - Documentation for the Lua math standard library - [model (Model)](#apis:model-lua) - Model API documentation - [msg (Message)](#apis:msg-lua) - Functions for passing messages and constructing URL objects - [os (Os)](#apis:os-lua) - Documentation for the Lua os standard library - [package (Package)](#apis:package-lua) - Documentation for the Lua package standard library - [particlefx (Particle effects)](#apis:particlefx-lua) - Functions and properties for controlling particle effect component playback and shader constants - [physics (Collision object)](#apis:physics-lua) - Collision object physics API documentation - [profiler (Profiler)](#apis:profiler-lua) - Functions for getting profiling data in runtime - [render (Render)](#apis:render-lua) - Rendering API documentation - [resource (Resource)](#apis:resource-lua) - Functions and constants to access resources - [socket (LuaSocket)](#apis:socket-lua) - [LuaSocket](https://github - [sound (Sound)](#apis:sound-lua) - Functions and messages for controlling sound components and mixer groups - [sprite (Sprite)](#apis:sprite-lua) - Sprite API documentation - [string (String)](#apis:string-lua) - Documentation for the Lua string standard library - [sys (System)](#apis:sys-lua) - Functions and messages for using system resources, controlling the engine, error handling and debugging - [table (Table)](#apis:table-lua) - Documentation for the Lua table standard library - [tilemap (Tilemap)](#apis:tilemap-lua) - Functions and messages used to manipulate tile map components - [timer (Timer)](#apis:timer-lua) - Timers allow you to set a delay and a callback to be called when the timer completes - [types (Types)](#apis:types-lua) - Functions for checking Defold userdata types - [vmath (Vector math)](#apis:vmath-lua) - Functions for mathematical operations on vectors, matrices and quaternions - [window (Window)](#apis:window-lua) - Functions and constants to access the window, window event listeners and screen dimming - [zlib (Zlib)](#apis:zlib-lua) - Functions for compression and decompression of string buffers ## Extension APIs - [adinfo (extension-adinfo)](#apis:extension-adinfo_adinfo) - Provides functionality to get the advertising id and tracking status - [admob (extension-admob)](#apis:extension-admob_admob) - Functions and constants for interacting with [Google AdMob APIs](https://developers - [adpf (extension-adpf)](#apis:extension-adpf_adpf) - Functions and constants for interacting with the Android Device Performance Framework - [camera (extension-camera)](#apis:extension-camera_camera) - Provides functionality to capture images using the camera - [crazygames (extension-crazygames)](#apis:extension-crazygames_crazygames) - Functions and constants for interacting with the CrazyGames SDK APIs - [crypt (extension-crypt)](#apis:extension-crypt_crypt) - Functions and constants for interacting with various hash and encode/decode algorithms - [facebook (extension-facebook)](#apis:extension-facebook_facebook) - Functions and constants for interacting with Facebook APIs - [firebase (extension-firebase-analytics)](#apis:extension-firebase-analytics_firebase) - Functions and constants for interacting with Firebase - [firebase (extension-firebase-remoteconfig)](#apis:extension-firebase-remoteconfig_firebase) - Functions and constants for interacting with Firebase - [firebase (extension-firebase)](#apis:extension-firebase_firebase) - Functions and constants for interacting with Firebase - [fmod (extension-fmod)](#apis:extension-fmod_fmod) - FMOD Low Level API for audio playback and manipulation - [fontgen (extension-fontgen)](#apis:extension-fontgen_fontgen) - Functions to generate glyphs for fonts at runtime - [instantapp (extension-googleplayinstant)](#apis:extension-googleplayinstant_instantapp) - Functions and constants for interacting with InstantApp APIs - [gpgs (extension-gpgs)](#apis:extension-gpgs_gpgs) - Functions and constants for interacting with Google Play Game Services (GPGS) APIs - [iac (extension-iac)](#apis:extension-iac_iac) - Functions and constants for doing inter-app communication - [iap (extension-iap)](#apis:extension-iap_iap) - Functions and constants for doing in-app purchases - [ironsource (extension-ironsource)](#apis:extension-ironsource_ironsource) - Functions and constants for interacting with IronSource API - [networkinfo (extension-network-info)](#apis:extension-network-info_networkinfo) - Functions to get information about the network configuration of the device - [odin (extension-odin)](#apis:extension-odin_odin) - Functions and constants for interacting with ODIN Voice - [pad (extension-pad)](#apis:extension-pad_pad) - Functionality to work with Play Asset Delivery and the AssetPackManager - [permissions (extension-permissions)](#apis:extension-permissions_permissions) - Functions and constants for interacting with permissions related APIs - [fusion (extension-photon-fusion)](#apis:extension-photon-fusion_fusion) - Functions and constants for interacting with Photon Fusion - [realtime (extension-photon-realtime)](#apis:extension-photon-realtime_realtime) - Functions and constants for interacting with Photon Realtime - [poki_sdk (extension-poki-sdk)](#apis:extension-poki-sdk_poki_sdk) - Functions and constants for interacting with Poki SDK APIs - [push (extension-push)](#apis:extension-push_push) - Functions and constants for interacting with local, as well as Apple''s and Google''s push notification services - [review (extension-review)](#apis:extension-review_review) - Functions and constants for interacting with review APIs - [rive (extension-rive)](#apis:extension-rive_rive) - Rive animation helpers exposed to Lua scripts - [safearea (extension-safearea)](#apis:extension-safearea_safearea) - Defold native extension that will change the view/render of a game to fit into the safe area on iPhones and Android(API 28+) with notch - [siwa (extension-siwa)](#apis:extension-siwa_siwa) - Functions and constants for interacting Sign in with Apple - [gui (extension-spine)](#apis:extension-spine_gui) - Functions and constants for interacting with Spine models in GUI - [spine (extension-spine)](#apis:extension-spine_spine) - Functions and constants for interacting with Spine models - [steam (extension-steam)](#apis:extension-steam_steam) - Functions and constants for interacting with Steamworks - [websocket (extension-websocket)](#apis:extension-websocket_websocket) - Functions and constants for using websockets - [webview (extension-webview)](#apis:extension-webview_webview) - Functions and constants for interacting with webview APIs - [shop (extension-xsolla)](#apis:extension-xsolla_shop) - Functions to use the Xsolla Shop Builder API - [zendesk (extension-zendesk)](#apis:extension-zendesk_zendesk) - Defold native extension to interact with the Zendesk SDK # Defold Examples This document contains Defold examples grouped by category. ## Animation - [Animation Delay - Wave](#examples:animation:animation_delay) - This example shows how to use the delay parameter of `go - [Cancel animation](#examples:animation:cancel_animation) - This example shows how to use `go - [Cursor animation](#examples:animation:cursor) - This example shows how to set and animate the normalized cursor value - [Custom easing - square wave](#examples:animation:custom_easing) - This example shows how to define a custom easing curve and use it when animating with `go - [Easing Functions (Tweens)](#examples:animation:easing) - Demonstrates different easing functions available in Defold - [Euler Rotation](#examples:animation:euler_rotation) - Shows how to animate Euler rotation - [Finite State Machines](#examples:animation:animation_states) - Shows how to build a small Finite State Machine module and use it to control character and animation states - [Flipbook animation](#examples:animation:flipbook) - This example shows how to use a flipbook animation in a sprite - [Spine animation](#examples:animation:spine) - This example shows Spine bone animation that blends when animation switches - [Spinner animation](#examples:animation:spinner) - This example shows how a game object is rotated in discrete steps, matching the graphics of the progress spinner - [Tween animation](#examples:animation:basic_tween) - This example shows how to tween animate the position of a game object - [Tween animations chain](#examples:animation:chained_tween) - This example shows how to chain two tween animations of the position of a game object ## Basics - [Message passing](#examples:basics:message_passing) - This example shows how to communicate between two script components in two separate game objects - [Parent/child](#examples:basics:parent_child) - This example shows how to child a game object to a parent - [Random numbers](#examples:basics:random_numbers) - This example shows how to generate pseudo-random numbers in Defold using built-in math API - [Z-order](#examples:basics:z_order) - This example shows how to put sprites in front and behind of eachother ## Collection - [Proxy](#examples:collection:proxy) - This example shows how to use collection proxies to load and unload collections - [Splash](#examples:collection:splash) - This example shows how to use collection proxies to show a splash screen while loading a game menu - [Time-step](#examples:collection:timestep) - This example shows how to speed up or slow down animations in a collection proxy by changing the time step of the collection proxy ## Debug - [Physics debug](#examples:debug:physics) - This example allows you to toggle physics debug visualization as well as changing the time step so the simulation runs at one tenth of the speed - [Visual profiler](#examples:debug:profile) - This example shows the on-screen profiler ## Factory - [Dynamic factories](#examples:factory:dynamic) - This example shows how to change the prototype game object used by a factory component - [Shoot bullets](#examples:factory:bullets) - This example shows how to dynamically spawn bullet game objects using a factory component - [Spawn enemies with central management](#examples:factory:spawn_manager) - This example shows how to spawn enemy game objects using a factory component and use a central manager to control movement and behavior of all enemies - [Spawn enemies with script properties](#examples:factory:spawn_properties) - This example shows how to spawn enemy game objects using a factory component with different properties - [Spawn game object](#examples:factory:basic) - This example shows how to dynamically spawn game objects with a factory component ## File - [Load JSON data](#examples:file:json_load) - This example shows how to load json data using sys - [Save and Load](#examples:file:sys_save_load) - This example shows how to save and load data using sys ## Gui - [Button](#examples:gui:button) - A GUI box node with an image texture and a script to make it act as a button - [Drag](#examples:gui:drag) - This example shows how to drag a GUI box node - [Get and set a gui font resource](#examples:gui:get_set_font) - This example shows how to get and set a font resource on a gui component - [Get and set a gui material resource](#examples:gui:get_set_material) - This example shows how to get and set a material resource on a gui component - [Get and set a gui texture resource](#examples:gui:get_set_texture) - This example shows how to get and set a texture resource on a gui component - [GUI color](#examples:gui:color) - This example shows how change the color of GUI nodes at run-time - [GUI progress indicators](#examples:gui:progress) - This example shows how to create various types of progress indicators - [Health Bar](#examples:gui:healthbar) - This example demonstrates how to add different health bars - [Layouts](#examples:gui:layouts) - This example demonstrates the use of layouts - [Load texture](#examples:gui:load_texture) - This example shows how to load and set a dynamic texture on a gui box node - [Localization (RTL/LTR)](#examples:gui:localization) - This example demonstrates how to handle localization in games, Unicode text layout, RTL rendering, and runtime font switching for localization - [Pointer over](#examples:gui:pointer_over) - A GUI box node with an image texture and a script that react when pointer over this node - [Slice-9](#examples:gui:slice9) - This example demonstrates slice-9 scaling gui box node - [Stencil](#examples:gui:stencil) - A GUI box node with "Clipping mode" set to "STENCIL" ## Input - [8 ways movement](#examples:input:move) - A very simple 8 ways movement setup with a single game object and a script that listens to input and updates the game object position accordingly - [Down duration](#examples:input:down_duration) - Listens to input trigger "touch" and count mouse down duration in update method - [Entity Picking](#examples:input:entity_picking) - This example demonstrates how to pick a game object from the 3D scene - [Mouse and touch events](#examples:input:mouse_and_touch) - Shows how to read mouse/touch movement and mouse/touch button state - [Text input](#examples:input:text) - Listens to text input trigger "type" and modifies the game object label with the alien's speech according to input ## Material - [Billboarding](#examples:material:billboarding) - This example shows how to make sprites and particle sprites face the camera using a custom vertex shader - [Custom Sprite](#examples:material:custom_sprite) - This example demonstrates a simple way to create and apply a custom sprite shader for changing colors and customizing an outline - [Noise shader](#examples:material:noise) - This example shows how to use a noise function to generate clouds, smoke or similar effect using a shader - [Repeating Background](#examples:material:repeating_background) - Create a scrolling background using a repeating texture on a model quad - [Screenspace](#examples:material:screenspace) - This example shows how to create a custom material with two textures that blend together to create a pattern effect using screen space coordinates - [Sprite local UV](#examples:material:sprite_local_uv) - This example shows how to get local UV coordinates of a sprite regardless of sprite size - [Sprite Vertex Color Attribute](#examples:material:vertexcolor) - This example shows how to set and animate a vertex attribute - [Unlit](#examples:material:unlit) - This example demonstrates how to create and apply an custom non-lit material to a 3D model - [UV Gradient](#examples:material:uvgradient) - This example shows how to apply a basic shader to a full screen quad - [Wave Background](#examples:material:wave_background) - Shows how to use a Time shader constant to achieve a moving wave effect ## Mesh - [Mesh](#examples:mesh:triangle) - This example shows how to create a basic mesh component in the shape of a triangle - [Textured Mesh](#examples:mesh:textured) - This example shows how to create a textured mesh component in the shape of a rectangle ## Model - [AABB](#examples:model:aabb) - This example demonstrates how to use the `model - [Character](#examples:model:character) - This example shows how to view and play skeletal animations on a glTF model - [Cubemap Reflection](#examples:model:cubemap) - This example shows how to use a cubemap to draw environment reflections on a model - [GLTF](#examples:model:gltf) - This example demonstrates how to use a glTF model - [GPU Skinning](#examples:model:skinning) - This example demonstrates GPU skinning - [Model Vertex Color](#examples:model:modelvertexcolor) - This example demonstrates how to apply a vertex color shader using exported attributes from a 3D model - [Skybox](#examples:model:skybox) - This example shows how to create a skybox using a cubemap texture ## Movement - [First-person 3D camera and movement](#examples:movement:3d_fps) - Control a first-person camera using WASD and mouse to look with cursor lock - [Follow input](#examples:movement:follow) - This example shows how to make a game object continuously follow the mouse - [Look at](#examples:movement:look_at) - This example shows how to rotate a game object to look at the mouse cursor - [Look rotation](#examples:movement:look_rotation) - This example shows how to rotate a game object to look at the object in 3D space - [Move forward](#examples:movement:move_forward) - This example shows how to move a game object in the direction it is rotated/facing - [Move to target](#examples:movement:move_to) - This example shows how to make a game object move to the position the user clicks - [Movement speed](#examples:movement:movement_speed) - This example shows how to move a game object with accelerating speed - [Moving game object](#examples:movement:simple_move) - This example shows how to move a game object ## Particles - [Modifiers](#examples:particles:modifiers) - This example shows particle effect modifiers - [Particle effect](#examples:particles:particlefx) - This example shows a simple particle effect - [Particle Effect Emission Space](#examples:particles:particlefx_emission_space) - This example demonstrates the difference between local and world particle emission spaces - [Particle effect example - fire and smoke](#examples:particles:fire_and_smoke) - This example shows a simple particle effect for imitating fire and smoke using two emitters and 3 modifiers in a single particlefx component - [ParticleFX - Confetti](#examples:particles:confetti) - This example shows a simple particle effect to imitate confetti with multiple emitters and global multipliers for all of them - [ParticleFX - Fountain - Start Delay](#examples:particles:particlefx_start_delay) - This example shows how the Start Delay emitter property can be used to sequence two emitters inside a single ParticleFX and create a simple fountain effect - [ParticleFX emitter properties](#examples:particles:particlefx_set_get) - This example shows how to get and set ParticleFX emitter image, animation, and material at runtime - [Spawning Fireworks ParticleFX](#examples:particles:fireworks) - This example shows how to spawn firework rockets with separate trail and burst particle effects, including a small dip before the burst ## Physics - [Apply force](#examples:physics:apply_force) - This example demonstrates how to apply directional force to all dynamic blocks on touch/click and draws debug direction lines - [Dynamic physics](#examples:physics:dynamic) - This example shows a simple setup with dynamic physics objects - [Fixed timestep interpolation](#examples:physics:interpolation) - This example shows how to smooth physics motion in fixed update mode by interpolating a visual sprite while keeping the physics body fixed-step - [Hinge joint physics](#examples:physics:hinge_joint) - This example shows a simple setup with a dynamic body physics object and two dynamic wheel physics object joined together with a joint of type "hinge" - [Kinematic physics](#examples:physics:kinematic) - This example shows a simple setup with a kinematic physics objects - [Knockback](#examples:physics:knockback) - This example shows how to create a knockback effect when hit - [Pendulum physics](#examples:physics:pendulum) - This example shows a simple setup with a static pivot and two dynamic weights - physics objects joined together with a joint of type "fixed" and "spring" - [Raycast](#examples:physics:raycast) - This example shows how to use physics raycasts to detect collisions along a straight line from a start point to an end point - [Trigger](#examples:physics:trigger) - This example shows how a physics trigger is used to trigger an event ## Render - [Camera](#examples:render:camera) - This example shows how to use a camera component and have it follow a game object - [Orbit Camera](#examples:render:orbit_camera) - This example demonstrates how to create script to control a 3D camera with the mouse - [Orthographic Zoom](#examples:render:orthographic_zoom) - This example shows how to zoom an orthographic camera in and out by changing Orthographic Zoom while the camera is in Fixed mode - [Post-processing](#examples:render:post_processing) - This example shows how to apply a post-processing effect by drawing to a render target and then to a fullscreen quad using a post processing shader - [Screen to World](#examples:render:screen_to_world) - This example shows how to convert from screen to world coordinates while using a camera - [World to Screen](#examples:render:world_to_screen) - This example demonstrates how to convert 3D world coordinates to 2D screen coordinates using camera transformations ## Resource - [Create atlas](#examples:resource:create_atlas) - This example shows how to create an atlas with two images and use it on a sprite and in a gui - [Modify atlas](#examples:resource:modify_atlas) - This example shows how to replace an image in an atlas ## Sound - [Fade In-Out](#examples:sound:fade_in_out) - This example shows how to make Fade-In and fade Fade-Out music - [Get and set sound](#examples:sound:get_set_sound) - This example shows how to change which sound a sound component plays - [Music](#examples:sound:music) - This example shows how to play a piece of music, stored as an - [Panning](#examples:sound:panning) - This example demonstrates how to pan a sound effect according to a GO's(game object) position on the screen ## Sprite - [Bunnymark](#examples:sprite:bunnymark) - This is a performance test for sprites - [Change sprite image](#examples:sprite:changeimage) - This example shows how to change the image of a sprite - [Flip](#examples:sprite:flip) - This example demonstrates flipping a sprite animation vertically and horizontally - [Multiple Sprite Samplers](#examples:sprite:samplers) - This example shows how to sample from more than one image when drawing a sprite - [Sprite cursor](#examples:sprite:cursor) - This example shows how to use the sprite animation cursor and frame count to manually select a specific frame - [Sprite size](#examples:sprite:size) - This example shows how to get the size of a sprite at run-time - [Sprite tint](#examples:sprite:tint) - This example shows how tint a sprite at run-time - [Texture scrolling](#examples:sprite:texture_scrolling) - This example shows how scroll the texture in the runtime using Texture Transform 2D Vertex Attribute, without using the sprite in the world space ## Tilemap - [Get and set tiles](#examples:tilemap:get_set_tile) - This example shows how to get and set tiles of a tilemap - [Tilemap collisions](#examples:tilemap:collisions) - This example shows how to detect collisions on tilemaps ## Timer - [Cancel timer example](#examples:timer:cancel_timer) - This example shows how to create timer and cancel it anytime, using built-in timer API - [Repeating timer example](#examples:timer:repeating_timer) - This example shows how to create timer that repeats endlessly every second - [Trigger timer example](#examples:timer:trigger_timer) - This example shows how to create timer that triggers counting every 1s and can be triggered manually and asynchronously as a reaction to user input ## Welcome to Defold {#manuals:introduction} Defold is a free, lightweight, and high-performance turnkey solution for the development of 2D and 3D games - a game engine, editor, and building ecosystem in one box, providing everything you need to design, build, and ship. The full list of supported features can be seen in our [Product Overview](https://defold.com/product). We have spent a lot of time and effort making sure that certain key elements of the game development process are as smooth and effortless as possible, and we believe it makes Defold stand out from the crowd. Learn [why we think you should use Defold](https://defold.com/why). ## Where to start? Our [**Learning Hub**](/learn) is a starting point for all learning resources for Defold. You'll find there: - [**Manuals**](/manuals) (like this one) - to deeply understand a given topic and broaden your knowledge - [**Tutorials**](/tutorials) - to create something by following guided step-by-step instructions - [**Examples**](https://defold.com/examples) - short snippets of code and simple, small, contained functionalities and samples - [**Courses**](/courses) - longer-form, comprehensive, structured lessons on Zenva, Udemy, and created by the community - [**Videos**](/videos) - if you prefer watching, there are a lot of video tutorials and overviews to choose from - [**API**](https://defold.com/ref/stable/overview_defoldlua) - understand all the provided functions and constants with our up-to-date full documentation - [**FAQ**](https://defold.com/faq/faq) - with answers to the most frequently asked questions - search to see if maybe your issue was already solved We encourage you to experiment, follow tutorials, read our manuals and API documentation, and join our [community channels](/community) - to ask questions, learn from other users, and follow the development of Defold. Here are some good-to-know pointers when starting your game development journey or learning Defold: ### Defold Editor [](#manuals:editor) [The Editor Overview](#manuals:editor) gives a good introduction to it and will help you get around, use the visual tools, and write code. If you are familiar with other game engines' editors, 3D modelling programs, and programming IDEs, there shouldn't be many surprises, but there are always things that will be different from your favorite piece of software. ### The building blocks of Defold [](#manuals:building-blocks) [Defold Building Blocks](#manuals:building-blocks) is a great introductory manual about the fundamental core concepts of game development in Defold. Defold uses game objects with multiple different kinds of components for building games, and game objects are then grouped into collections. These might seem familiar if you have used other engines before. There are some architectural design decisions that make the building blocks of Defold special, and it takes a moment to become comfortable working with them. Therefore, our building blocks manual is a good start, especially if you feel you need to understand how it works. ### Examples [](https://defold.com/examples) [Examples](https://defold.com/examples/) collection is a good introduction to how to put pieces together into something that works. You will find there minimal examples of how to do a wide variety of common things in Defold, code snippets to use, samples of some common functionalities, and showcases of certain features. ### Tutorials [](/tutorials) [Tutorials](/tutorials) are great for starting your game development journey. We believe that you learn best by doing. That is why we have a selection of tutorials at various skill and complexity levels available directly from [the editor](#manuals:editor) and in our learning hub. Fire it up and follow step-by-step instructions to learn how to build things and how Defold works. ### The Lua language [](#manuals:lua) [Lua](#manuals:lua) is the language used in Defold for all its logic control. The engine internally is a fast C++ piece of machinery, but it is controlled at a high level by Lua scripts. If you have programmed in Python, GDScript, GML, Javascript, or any other high-level language, you will find Lua pretty easy to grasp and can probably follow along with a tutorial just fine. Otherwise, read through our Lua manual and take it from there. ### The Defold Forum [](//forum.defold.com/) [The Defold Forum](//forum.defold.com/) is often the best way to learn - you can learn from others, search the forum to find whether your issue was answered in the past, or ask directly. Our community is very friendly, helpful, and knows a lot about building games in general and Defold in particular. If you ever get stuck, don't hesitate, but head over to the forum for help! ### Learning Hub Remember that no matter what path you take to learning Defold, you can always come back to our [**Learning Hub**](/learn) to find any other learning resources and read manuals for in-depth explanations of the various features and concepts Defold provides. And don't hesitate to point out things that you do not understand or think are wrong. These pages are for you, and we want to make them as good as possible, so we take users' feedback into account and try to improve the resources to make the learning curve as smooth as possible! We hope that you will enjoy creating your next awesome game in Defold! # Installing Defold {#manuals:install} Installation of the Defold editor is quite straightforward. Download the version built for your operating system, extract it and copy the software to a suitable location. ## Downloading Go to the [Defold download page](https://defold.com/download/) where you will find Download buttons for macOS, Windows and Linux (Ubuntu): ## Installation Installation on macOS : The downloaded file is a DMG image containing the program. 1. Locate the file "Defold-x86_64-macos.dmg" and double click it to open the image. 2. Drag the application "Defold" to the "Applications" folder link. To start the editor, open your "Applications" folder and `double click` the file "Defold". Installation on Windows : The downloaded file is a ZIP archive that needs to be extracted: 1. Locate the archive file "Defold-x86_64-win32.zip", `press and hold` (or `right-click`) the folder, select *Extract All*, and then follow the instructions to extract the archive to a folder named "Defold". 2. Move the folder "Defold" to your preferred location (e.g. `D:\\Defold`). You should not move Defold to `C:\\Program Files (x86)\\` or `C:\\Program Files\\` since this will prevent the editor from updating. To start the editor, open the folder "Defold" and `double click` the file "Defold.exe". Installation on Linux : The downloaded file is a ZIP archive that needs to be extracted: 1. From a terminal, locate the archive file "Defold-x86_64-linux.zip" unzip it to a target Directory called "Defold". ```bash $ unzip Defold-x86_64-linux.zip -d Defold ``` To start the editor, change directory to where you extracted the application, then run the `Defold` executable, or `double click` it on your desktop. ```bash $ cd Defold $ ./Defold ``` There is a helper to install a desktop entry on the `Help > Create Desktop Entry` menu. If you run into any problems starting the editor, opening a project or running a Defold game please refer to the [Linux section of the FAQ](https://defold.com/faq/faq#linux-questions). ## Install an old version Every beta and stable version of Defold is also [available on GitHub](https://github.com/defold/defold/releases). # Defold glossary {#manuals:glossary} This glossary gives a brief description to all the things you encounter in Defold. In most cases, you will find a link to more in-depth documentation. ## Animation set An animation set resource contains a list of .dae files or other .animationset files from where to read animations. Adding one .animationset files to another is handy if you share partial sets of animations between several models. See the [model animation manual](#manuals:model-animation) for details. ## Atlas An atlas is a set of separate images that are compiled into a larger sheet for performance and memory reasons. They can contain still images or flip-book animated series of images. Atlases are used by a variety of components to share graphics resources. See the [Atlas documentation](#manuals:atlas) for more information. ## Builtins The builtins project folder is a read-only folder containing useful default resources. Here you find the default renderer, render script, materials and more. If you need custom modifications on any of these resources, simply copy them into your project and edit as you see fit. ## Camera The camera component helps to decide what part of the game world should be visible and how it should be projected. A common use case is to attach a camera to the player game object, or to have a separate game object with a camera that follows the player around with some smoothing algorithm. See the [Camera documentation](#manuals:camera) for more information. ## Collision object Collision objects are components that extend game objects with physical properties (like spatial shape, weight, friction and restitution). These properties govern how the collision object should collide with other collision objects. The most common types of collision objects are kinematic objects, dynamic objects and triggers. A kinematic object gives detailed collision information that you have to manually respond to, a dynamic object is automatically simulated by the physics engine to obey Newtonian laws of physics. Triggers are simple shapes that detect if other shapes have entered or exited the trigger. See the [Physics documentation](#manuals:physics) for details on how this works. ## Component Components are used to give specific expression and/or functionality to game objects, like graphics, animation, coded behavior and sound. They don’t live a life of their own but have to be contained inside game objects. There are many kinds of components available in Defold. See [the Building blocks manual](#manuals:building-blocks) for a description of components. ## Collection Collections are Defold’s mechanism for creating templates, or what in other engines are called "prefabs" in where hierarchies of game objects can be reused. Collections are tree structures that hold game objects and other collections. A collection is always stored on file and brought into the game either statically by placing it manually in the editor, or dynamically by spawning. See [the Building blocks manual](#manuals:building-blocks) for a description of collections. ## Collection factory A Collection factory component is used to spawn hierarchies of game objects dynamically into a running game. See the [Collection factory manual](#manuals:collection-factory) manual for details. ## Collection proxy A Collection proxy is used to load and enable collections on the fly while an app or game is running. The most common use case for Collection proxies is to load levels as they are to be played. See the [Collection proxy documentation](#manuals:collection-proxy) for details. ## Cubemap 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. ## Display profiles The display profiles resource file is used for specifying GUI layouts depends on the orientation, aspect ratio or device model. It helps to adapt your UI for any kind of devices. Read more in the [Layouts manual](#manuals:gui-layouts). ## Factory 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 preallocated pool of objects), you use a factory component. See the [Factory manual](#manuals:factory) for details. ## Font 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 This is a program that is run on the graphics processor for each pixel (fragment) in a polygon when it is drawn to the screen. The purpose of the fragment shader is to decide the color of each resulting fragment. This is done by calculation, texture lookups (one or several) or a combination of lookups and computations. See the [Shader manual](#manuals:shader) for more information. ## Gamepads A gamepads resource file defines how specific gamepad device input is mapped to gamepad input triggers on a certain platform. See the [Input manual](#manuals:input) for details. ## Game object Game objects are simple objects that have a separate lifespan during the execution of your game. Game objects are containers and are usually equipped with visual or audible components, like a sound or a sprite. They can also be equipped with behavior through script components. You create game objects and place them in collections in the editor, or spawn them dynamically at run-time with factories. See [the Building blocks manual](#manuals:building-blocks) for a description of game objects. ## GUI A GUI component contains elements used to construct user interfaces: text and colored and/or textured blocks. Elements can be organized into hierarchical structures, scripted and animated. GUI components are typically used to create heads-up displays, menu systems and on-screen notifications. GUI components are controlled with GUI scripts that define the behavior of the GUI and control the user interaction with it. Read more in the [GUI documentation](#manuals:gui). ## GUI script 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 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. ## Label The label component allows you to attach text content to any game object. It renders a piece of text with a particular font, on screen, in game space. See the [Label manual](#manuals:label) for more information. ## Library 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 modules allow you to structure your project and create reusable library code. Read more about it in the [Lua modules manual](#manuals:modules) ## Material Materials define how different objects should be rendered by specifying shaders and their properties. See the [Material manual](#manuals:material) for more information. ## Message Components communicate with each other and other systems through message passing. Components also respond to a set of predefined messages that alter them or trigger specific actions. You send messages to hide graphics or nudge physics objects. The engine also uses messages to notify components of events, for instance when physics shapes collide. The message passing mechanism needs a recipient for each sent message. Therefore, everything in the game is uniquely addressed. To allow communication between objects, Defold extends Lua with message passing. Defold also provides a library of useful functions. For instance, the Lua-code required to hide a sprite component on a game object looks like this: ```lua msg.post("#weapon", "disable") ``` Here, `"#weapon"` is the address of the current object's sprite component. `"disable"` is a message that sprite components respond to. See the [Message passing documentation](#manuals:message-passing) for an in depth explanation of how message passing works. ## Model The 3D model component can import glTF mesh, skeleton and animation assets into your game. See the [Model manual](#manuals:model) for more information. ## ParticleFX 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 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. ## Render script A Render script is a Lua script that controls how the game or app should be rendered to the screen. There is a default Render script that covers most common cases, but you can write your own if you need custom lighting models and other effects. See the [Render manual](#manuals:render) for more details on how the render pipeline works, and the [Lua in Defold manual](#manuals:lua) for details on how Lua scripts are used in Defold. ## Script A script is a component that contains a program that defines game object behaviors. With scripts you can specify the rules of your game, how objects should respond to various interactions (with the player as well as other objects). All scripts are written in the Lua programming language. To be able to work with Defold, you or someone on your team needs to learn how to program in Lua. See the [Lua in Defold manual](#manuals:lua) for an overview on Lua and details on how Lua scripts are used in Defold. ## Sound The sound component is responsible for playing a specific sound. Currently, Defold supports sound files in the WAV and Ogg Vorbis formats. See the [Sound manual](#manuals:sound) for more information. ## Sprite A sprite is a component that extends game objects with graphics. It displays an image either from a Tile source or from an Atlas. Sprites have built-in support for flip-book and bone animation. Sprites are usually used for characters and items. ## Texture profiles The texture profiles resource file is used in the bundling process to automatically process and compress image data (in Atlas, Tile sources, Cubemaps and stand-alone textures used for models, GUI etc). Read more in the [Texture profiles manual](#manuals:texture-profiles). ## Tile map Tile map components display images from a tile source in one or more overlaid grids. They are most commonly used to build game environments: ground, walls, buildings and obstacles. A tile map can display several layers aligned on top of each other with a specified blend mode. This is useful to, for example, put foliage on top of grass background tiles. It is also possible to dynamically change the displayed image in a tile. That allows you to, for instance, destroy a bridge and make it impassable by simply replacing the tiles with ones depicting the broken down bridge and containing the corresponding physics shape. See the [Tile map documentation](#manuals:tilemap) for more information. ## Tile source A tile source describes a texture that is composed of multiple smaller images, each with the same size. You can define flip-book animations from a sequence of images in a tile source. Tile sources can also automatically calculate collision shapes from image data. This is very useful for creating tiled levels that object can collide and interact with. Tile sources are used by Tile map components (and Sprite and ParticleFX) to share graphics resources. Note that Atlases are often a better fit than tile sources. See the [Tile map documentation](#manuals:tilemap) for more information. ## Vertex shader The vertex shader computes the screen geometry of a component's primitive polygon shapes. For any type of visual component, be it a sprite, tilemap or model, the shape is represented by a set of polygon vertex positions. The vertex shader program processes each vertex (in world space) and computes the resulting coordinate that each vertex of a primitive should have. See the [Shader manual](#manuals:shader) for more information. # Defold for Unity users {#manuals:unity} If you have prior experience with Unity, this guide helps you become productive in Defold quickly. It focuses on essentials and points you to the official Defold manuals whenever deeper details are needed. ## Introduction Defold is a completely free, truly cross-platform 3D game engine with an Editor for Windows, Linux, and macOS. The full source code is available on [Github](https://github.com/defold/defold/). Defold is focused on performance, even on low-end devices. It uses a small component model where many gameplay interactions are handled through code and message passing. Defold is much smaller than Unity. Engine size with empty project is between 1-3 MB on all platforms. You can strip out additional parts of the engine, and move some game content into [Live Update](#manuals:live-update) to download separately later. A size comparison and other reasons to choose Defold are described on the [Why Defold webpage](https://defold.com/why/). To customize Defold to your needs, you can write your own or use existing: 1. Fully scriptable rendering pipeline (render script + materials/shaders) with few backends to choose from (OpenGL, Vulkan, etc.). 2. Code and components as Native Extensions (C++/C#). 3. Editor Scripts and UI widgets to customize Editor. 3. Altered build of the engine and editor, as the full source code and a build pipeline is available. We also recommend checking out a video by Game From Scratch about [Defold for Unity developers](https://www.youtube.com/watch?v=-3CzCbd4QZ0). ## Welcome screen Defold greets you with a welcome screen similar to the Unity Hub, where you can open recent projects: Or start a new one from: - `Templates` - basic empty projects for quicker setup for a specific platform or genre, - `Tutorials` - guided learning tours that help you take your first steps, - `Samples` - official or community-contributed use cases and examples, When you create your first project and/or open it, it will open in the Defold Editor. ## Hello World This is a quick way to get something done in Defold quickly, follow the steps, and then get back to read the rest of the manual. 1. Select an empty project from `Templates`, name it in `Title`, choose location and create it by clicking `Create New Project`. It will open in the Defold Editor. 2. On the left side, in the `Assets` pane, open the `main` folder and double click on the `main.collection` to open it. 3. On the right side, in the `Outline` pane right-click on the `Collection` and select `Add Game Object`. 4. Right-click on the created `go` game object and select `Add Component`, and then `Label`. 5. Below, on the left side, in the `Properties` pane type something in the `Text` property. 6. In the main, central scene view, drag, move and drop the label to position around `(480,320,0)`, or change it in `Properties`: `Position`. 7. After changing the label position, save the project by clicking `File` -> `Save All` or shortcut `Ctrl`+`S` (`Cmd`+`S` on Mac). 8. Built your project by clicking `Project` -> `Build` or shortcut `Ctrl`+`B` (`Cmd`+`B` on Mac). You just build your first project in Defold and should see your text in the window. The concepts of game object and component should be familiar to you. The collections, outline, properties and why we needed to move the label a bit in the top-right direction are explained below. ## Key Concepts If you generalize enough, the key concepts behind most game engines are very similar. They’re meant to help developers build games more easily, like assembling blocks, while handling complex and platform related tasks on their own. ### Building Blocks Defold operates with just a few basic building blocks: For more details, check the full manual about [Defold building blocks](#manuals:building-blocks). ### Game Objects Defold uses **"Game Objects"**, similar to Unity. In both engines, game objects are containers for data with an ID, and they all have transforms: position, rotation, and scale, but in Defold, the transform is built-in rather than a separate component. You can create parent-child relationships between game objects. In Defold, this can be done only in the Editor inside a "Collection" (explained below) or dynamically in script. Game objects cannot contain other game objects as nested objects the way they can in Unity. ### Components In both engines, Game Objects can be extended with **"Components"**. Defold provides a minimal set of essential components. There is less distinction between 2D and 3D than in Unity (e.g., colliders), so there are fewer components overall, and some from Unity you may miss. #### Behaviour components In Unity, "component" usually means a `MonoBehaviour` that is attached to a `GameObject`. You can create your own by inheriting from `MonoBehaviour` or you can use their built-in components like Light, some physics stuff, something something, so on and so forth. In Defold, Component refers exclusively to what would be the equivalent built-in components in Unity, or something, but defold does not treat a script as a monobehaviour and does not require any explicit "marking" in order to attach to a gameobject, other than creating listener events/callbacks. Custom gameplay behaviour is usually not added as many separate script components on the same game object. Instead, it is commonly implemented in Lua modules and used by one host `.script`, or handled by a larger system script that controls many objects. The Code Writing section below covers this in more detail. Read more about [Defold Components here](#manuals:components). The table below presents similar Unity components for quick lookup, with links for each Defold component manual: | Defold | Unity | Differences | |---|---|---| | [Sprite](#manuals:sprite) | Sprite Renderer | In Defold, you can change the tint (color property) only via code. | | [Tilemap](#manuals:tilemap) | Tilemap / Grid | Defold has a built-in Tilemap Editor that supports square grids (but there’s an extension for, e.g. [Hexagon](https://github.com/selimanac/defold-hexagon/)) and has no built-in autotiling rules. Tools like [Tiled](https://defold.com/assets/tiled/), [TileSetter](https://defold.com/assets/tilesetter/) or [Sprite Fusion](https://defold.com/assets/spritefusion/) have export to Defold options. | | [Label](#manuals:label) | Text / TextMeshPro | Defold has a [RichText extension](https://defold.com/assets/richtext/) for rich formatting (similar to TextMeshPro). | | [Sound](#manuals:sound) | AudioSource | Defold has only a global sound source (not spatial). There is an official [FMOD extension](https://github.com/defold/extension-fmod) for Defold. | | [Factory](#manuals:factory) | Prefab Instantiate() | In Defold, a Factory is a component with a specific prototype (prefab). | | [Collection Factory](#manuals:collection-factory) | - (No direct component equivalent) | A Collection Factory component in Defold can spawn multiple Game Objects with parent-child relationships at once. | | [Collision Object](#manuals:physics-objects) | Rigidbody + Collider | In Defold, physics objects and collision shapes are combined in a single component. | | [Collision Shapes](#manuals:physics-shapes) | BoxCollider / SphereCollider / CapsuleCollider | In Defold, shapes (box, sphere, capsule) are configured inside the Collision Object component. Both support collision shapes from tilemaps and convex hull data. | | [Camera](#manuals:camera) | Camera | In Unity, the camera has some more built-in rendering and post-processing settings, while Defold delegates it for custom control for user via the render script. | | [GUI](#manuals:gui) | UI Toolkit / Unity UI / uGUI Canvas | Defold GUI is a powerful component for building complete UIs and templates. Unity doesn’t have an equivalent single UI component, rather multiple UI frameworks. Defold has an extension for [Extension](https://github.com/britzl/extension-imgui) too. | | [GUI Script](#manuals:gui-script) | Unity UI / uGUI scripts | Defold GUI can be controlled via GUI scripts using the dedicated `gui` API. | | [Model](#manuals:model) | MeshRenderer + Material | In Defold, a Model component bundles a 3D model file, textures, and a material with shaders. | | [Mesh](#manuals:mesh) | MeshRenderer / MeshFilter / Procedural Mesh | In Defold, Mesh is a component for managing a vertex set via code. It’s similar to a Defold Model, but even more low-level. | | [ParticleFX](#manuals:particlefx) | Particle System | Defold’s particle editor supports 2D/3D particle effects with many properties, and lets you animate them over time using curves in the Curve Editor. It has no Trails or Collisions. | | [Script](#manuals:script) | Script | More details on programming differences explained below. | #### Extensions and custom components Defold also has official [Spine](/extension-spine/) and [Rive](/extension-rive/) components available via extensions. You can also create your own [custom Components](https://github.com/defold/extension-simpledata) using Native Extensions, like e.g. this community created [Object Interpolation Component](https://github.com/indiesoftby/defold-object-interpolation). Some Unity components have no out-of-the-box equivalent in Defold, for example: Audio Listener, Light, Terrain, LineRenderer, TrailRenderer, Cloth or Animator. However, all of this functionality can be implemented in scripts, and there are already solutions available—for example, different lighting pipelines, the Mesh component for generating arbitrary meshes (including terrain), or [Hyper Trails](https://defold.com/assets/hypertrails/) for customizable trail effects. Defold may also add new built-in components in the future, such as lights. ### Resources Some Components require **"Resources"**, similar to Unity, for example, sprites and models need textures. A few of them are compared in the table below: | Defold | Unity | Differences | |---|---|---| | [Atlas](#manuals:atlas) | Sprite Atlas / Texture2D | Defold also has an [extension for Texture Packer](https://defold.com/extension-texturepacker/). | | [Tile source](#manuals:tilesource) | Tile Palette + Asset | In Defold, a tile source can be used as the texture for tilemaps, but also for sprites or particles. | | [Font](#manuals:font) | Font | Used by the Defold Label component or text nodes in GUI, similar to Text/TextMeshPro in Unity. | | [Material](#manuals:material) | Material | In Defold, shaders are named: vertex program and fragment program. | ### Collection vs Scene In Defold Game Objects and Components can be placed in separate files, like Unity prefabs, or be defined in a combining **"Collection"** file. A Collection in Defold is essentially a text file with a static scene description. It is **not** a runtime object. It only defines what Game Objects should be instantiated in the game and how parent-child relationships between those objects should be established. #### Game Worlds Unity scenes share by default the same global game state and physics simulation, effectively the same *world*. In Defold, you have two options: 1. Instantiate game objects from a single game object file via a `Factory` or a collection file via a `Collection Factory` to a given, instantiated already *world*, like prefabs. 2. Create a separate game *world* at runtime, with its own game objects, physics world, engine operations and addressing namespace via a collection loaded at bootstrap or via a `Collection Proxy` component. Factories and Proxy components are also explained below. Read more about Collections in the [Building Blocks manual](#manuals:building-blocks). ## Code Writing A Defold equivalent to `MonoBehaviour` scripts is a Script component, but there are some worth knowing differences. ### Lua Defold scripts are written in a dynamically typed, multi-paradigm [Lua](https://www.lua.org/) language. There are few types of Lua scripts: `*.script`, `*.gui_script`, `*.render_script`, `*.editor_script`, and `*.lua` modules. ### Teal Defold supports the usage of transpilers that emit Lua code, such as [Teal](https://teal-language.org/) - a statically-typed dialect of Lua, but this functionality is more limited and requires additional setup. Details are available in the [Teal Extension Repository](https://github.com/defold/extension-teal). ### C++/C# Native Extensions In Defold Native Extensions can be written in several other languages: C, C++, C#, Objective-C, Java or JS depending on target platform. If you are very comfortable with C#, it’s technically possible to structure most of your game logic in a C# extension and just call it from a small Lua bootstrap script, though this requires some advanced API knowledge and is not recommended for beginners. Read more about extensions in [Defold Native Extensions manual](#manuals:extensions). ### From MonoBehaviours to Lua modules Unity has an open scripting model. Because `MonoBehaviour` is the primary way to add behaviour in the editor, many Unity projects start with one controller-style script per important GameObject: `PlayerController`, `EnemyController`, `BulletController`, `GameManager`, `EnemyManager`, and so on. Defold is more specific about its default architecture. A game object may have a `.script`, but you rarely need to create a script for every Game Object, because a single script in Defold can control hundreds or thousands of other objects and their components, without them even having any scripts of their own, thanks to the Defold's powerful addressing and message passing. Creating scripts to match each Game Object is rarely necessary and can lead to counterproductive complexity. For reusable gameplay behaviour, Unity developers often move toward composition: smaller `MonoBehaviour` scripts such as `Health.cs`, `Attack.cs`, or `EnemyFinder.cs` attached to the same GameObject. In Defold, you usually keep one attached `.script` as the host or coordinator and put reusable logic in regular Lua modules. In Unity, this composition might look like this: ```text Player ├── PlayerMovement.cs ├── PlayerAttack.cs ├── EnemyFinder.cs └── Health.cs ``` In Defold, the same responsibilities are often split between one attached script and reusable modules: ```text player.go ├── sprite ├── collisionobject └── player.script modules/ ├── player_movement.lua ├── player_attack.lua ├── enemy_finder.lua └── health.lua ``` The attached `.script` becomes the host or coordinator. The Lua modules contain reusable logic, similar to how small `MonoBehaviour` scripts often contain one responsibility in Unity. ```lua local movement = require "modules.player_movement" local attack = require "modules.player_attack" local finder = require "modules.enemy_finder" local health = require "modules.health" function init(self) self.movement = movement.new(self) self.attack = attack.new(self) self.finder = finder.new(self) self.health = health.new(self) end function update(self, dt) self.movement:update(dt) self.attack:update(dt) self.finder:update(dt) end function on_message(self, message_id, message, sender) self.health:on_message(message_id, message, sender) self.attack:on_message(message_id, message, sender) end ``` The important difference is not that Defold prevents modular architecture - it is where composition happens and how gameplay code communicates: | Unity | Defold | |---|---| | Attach several `MonoBehaviour` scripts in the Inspector | Attach one `.script` and compose Lua modules in code | | Use `GetComponent()` or serialized fields to connect behaviours | Store module instances on `self` and use addresses/messages between objects | | Each component can have its own lifecycle methods | The host script routes `init()`, `update()`, `on_message()`, `final()`, etc. | | Many architectural styles are possible | Messaging-oriented, explicit code composition is the common practice | This can feel unusual at first, especially if you are used to configuring behaviour by adding components in the Inspector. In Defold, many things that you might configure visually in Unity can instead be created, connected, enabled, disabled, or updated through code. Defold's messaging system helps decouple logic: the sender posts data to an address, and the receiver decides what to do with it. This approach, even though recommended, is not enforced and you can still write your scripts however you like, including attaching multiple scripts per game object or getting closer to an object oriented style of programming, and there are even libraries to help you with this ([defold-oop](https://github.com/xiyoo0812/defold-oop) or [lua-class](https://github.com/d954mas/lua-class)). For many objects of the same type, such as bullets, enemies, particles, tiles, or simple interactive elements, it is often better to control them from a system or manager script rather than giving each object a separate script. Use per-object scripts when an object has its own meaningful state and behaviour. Use modules when you want reusable logic. Use system scripts when one script can efficiently control many objects. An example showing how to utilise Defold script properties, factories, addressing, and messaging to control multiple units can be found [here](https://defold.com/examples/factory/spawn_manager/). Good manuals on code writing: - [Script manual](#manuals:script) - [Writing code](#manuals:writing-code) - [Debugging](#manuals:debugging) ### Built-in Code Editor Defold Editor includes a built-in code editor with code completion, syntax highlighting, quick documentation lookup, linting, and a built-in debugger. ### VS Code and other editors You can still use your own external editor if you prefer. All Defold components and related files are text based, so you can edit them with any text editor, but you must follow the proper formatting and element structure, since they are Protobuf-based. If you are used to VS Code and want to use it to write your game’s code, we recommend installing [Defold Kit](https://marketplace.visualstudio.com/items?itemName=astronachos.defold) or [Defold Buddy](https://marketplace.visualstudio.com/items?itemName=mikatuo.vscode-defold-ide) from the Visual Studio Marketplace. You can also configure Defold Editor preferences to open text files by default in VS Code (or any other external editor). See [Editor Preferences](#manuals:editor-preferences) for details. ### Shaders - GLSL Defold uses GLSL (the OpenGL Shading Language) for shaders - `Vertex Programs` and `Fragment Programs`, similar to Unity. Although Defold doesn’t offer a Shader Graph like Unity (which may be a downside), you can still create equivalent shaders by writing code. Read more about shaders in the [Shaders manual](#manuals:shader). #### Materials Defold uses a concept of `Material` that connects `.fp` and `.vp` shaders, samplers (textures) and other things like Vertex Attributes or Constants. Read more about materials in the [Materials manual](#manuals:material). ## Prefabs and instances Unity can instantiate anything in the Scene statically or dynamically, and Defold can do the same. In Unity you take a Prefab and call `Instantiate(prefab)`. In Defold you have 3 components for instantiating content: - `Factory` - instantiates a **single Game Object** from a given prototype: a `*.go` file (prefab). - `Collection Factory` - instantiates a **set of Game Objects** with parent-child relationships from a given prototype: a `*.collection` file. - `Collection Proxy` - **loads** and instantiates a new *world* from a `*.collection` file. ### Factory Once you have a `Factory` component defined with its `Prototype` property set to the appropriate Game Object file, spawning is as simple as calling in code: ```lua factory.create("#my_factory") ``` This uses the address of the component, in this case - a relative path using the identifier `"#my_factory"`. It returns the identifier of the newly created instance, so if you need to use it later, it’s worth storing it in a variable: ```lua local new_instance_id = factory.create("#my_factory") ``` Remember that in Defold you don’t need to manually pool objects - the engine itself does pooling internally for you. Check more details in the [Factory manual](#manuals:factory). ### Collection Factory The difference between `Factory` and `Collection Factory` component is that Collection Factory can spawn **multiple** game objects at once, and define at creation the parent-child relationships as defined in the `*.collection` file. Such a distinction is not present in Unity, it doesn't have a dedicated concept that matches Defold's Collection Factory. The closest analogy is just a nested Prefab that contains a hierarchy of objects. It returns a **table** with ids of all spawned instances: ```lua local spawned_instances = collectionfactory.create("#my_collectionfactory") ``` Check more details in the [Collection Factory manual](#manuals:collection-factory). #### Custom properties of instances When calling `factory.create()` or `collectionfactory.create()` you can also specify optional parameters such as position, rotation, scale and script properties, so you can control exactly how and where the instance appears, and how it behaves e.g.: ```lua factory.create("#my_factory", my_position, my_rotation, my_scale, my_properties) ``` #### Dynamic Loading In both `Factory` and `Collection Factory` components you can mark a Prototype for dynamic resource loading so that its heavy assets are only pulled into memory when needed, and unloaded when they’re no longer used. Check more details in the [Resource Management manual](#manuals:resource). ### Collection Proxy The `Collection Proxy` refers to a specific `*.collection` file, but instead of injecting the objects into the *current world* (like factories), it **loads and instantiates a new game world**. This is somewhat similar to loading an entire scene in Unity, but with stricter separation. In Unity you might load an additive scene like this: ```c# SceneManager.LoadSceneAsync("Level2", LoadSceneMode.Additive); ``` In Defold you load the new collection just by sending a message to the `Collection Proxy` component: ```lua msg.post("#myproxy", "load") ``` 1. When you send the proxy a message `"load"` (or `"async_load"` for asynchronous loading), the engine allocates a new world, instantiates everything in that collection there, and keeps it isolated. 2. Once loaded, the proxy sends back a `"proxy_loaded"` message indicating the world is ready. 3. You then typically send `"init"` and `"enable"` messages so the objects in that new world begin their normal lifecycle. To communicate between the loaded worlds, you have to use explicit messaging with URLs that include the world name (`collection:`, the first part of the URL). This isolation can be a huge advantage when implementing level transitions, mini-games, or large modular systems, because it prevents unintended interactions, and also allows separate control over update timing if needed (e.g. for pause or slow motion). If you’ve ever used multiple scenes in Unity and needed them to behave independently, think of a `Collection Proxy` as a way to bring that concept directly into Defold. Check more details in the [Collection Proxy manual](#manuals:collection-proxy). ## GUI Defold’s GUI is a whole single dedicated framework for User Interfaces - menus, overlays, dialogs, and other elements, similar to UI Toolkit or uGUI with Canvas. GUI is a Component, and is separate from Game Objects and Collections. Instead of Game Objects, you work with GUI nodes arranged in a hierarchy, driven by a GUI script. ### GUI Nodes When you open a `*.gui` component file in Defold, you are presented with canvas where you place `"GUI nodes"`. These are the building blocks of the GUI. You can add GUI nodes of type: - Box (rectangular shape with a texture) - Text (with any font) - Pie (radial fill pie-slice element with a texture) - ParticleFX - Template (another whole nested `.gui` file, like a GUI prefab) - and Spine node, when using Spine extension. ### GUI Script GUI component have a special property for GUI scripts - you assign one `*.gui_script` file per component and it allows to modify the behaviour of the component, so it's very similar to regular scripts, except it doesn’t use the `go.*` namespace (which is for game object scripts). Instead, it uses a special `gui.*` namespace API that only works inside GUI scripts (`*.gui_script`). You can think of it like a separate Scene. Unity UI (uGUI) with Canvas. ### GUI Rendering GUI elements are rendered independently of the game camera, typically in screen-space, but this behavior can be changed in custom rendering pipelines. For further details read the [GUI Manual](#manuals:gui). ## Where are Sorting Layers? This is a very common Unity migration confusion. GUI components have `Layers` and this works almost the same as "Sorting Layers" in Unity, but for other components, like `Sprites`, `Tilemaps`, `Models`, etc, there is no direct equivalent. Instead, you typically combine: - Fine ordering via Z axis when using a default camera or depth when using a Camera component. - Coarse ordering via the render script using render predicates - to select what to draw by material tags. But you shouldn’t mimic Unity Sorting Layers with lots of tags, because in Defold, tags are a render-level mechanism. Overusing them can break batching and raise draw overhead. --- ## Where to go from here? - [Defold examples](https://defold.com/examples) - [Tutorials](/tutorials) - [Manuals](/manuals) - [API References](https://defold.com/ref/go) - [FAQ](https://defold.com/faq/faq) If you have questions or get stuck, the [Defold Forum](//forum.defold.com) or [Discord](https://defold.com/discord/) are great places to reach out for help. # Defold for Flash users {#manuals:flash} This guide presents Defold as an alternative for Flash game developers. It covers some of the key concepts used in Flash game development, and explains the corresponding tools and methods in Defold. ## Introduction Some of the key advantages of Flash were the accessibility and low barriers to entry. New users could learn the program quickly, and could be creating basic games with limited time investment. Defold offers a similar advantage by providing a suite of tools dedicated to game design, while empowering advanced developers to create advanced solutions for more sophisticated requirements (for instance by allowing developers to edit the default render script). Flash games are programmed in ActionScript (with 3.0 being the most recent version), while Defold scripting is done in Lua. This guide will not go into a detailed comparison of Lua and Actionscript 3.0. The [Defold manual](#manuals:lua) provides a good introduction to Lua programming in Defold, and references the tremendously useful [Programming in Lua](https://www.lua.org/pil/) (first edition) which is freely available online. An article by Jesse Warden provides a [basic comparison of Actionscript and Lua](http://jessewarden.com/2011/01/lua-for-actionscript-developers.html), which may serve as a good starting point. Note thought that there are deeper differences in how Defold and Flash are constructed than what is visible at the language level. Actionscript and Flash is object oriented in the classical sense with classes and inheritance. Defold does not have classes, nor inheritance. It includes the concept of a *game object* which can contain audiovisual representation, behavior and data. Operations on game objects are done with *functions* available in the Defold APIs. Furthermore, Defold encourages the use of *messages* to communicate between objects. Messages are a higher level construct than method calls and are not intended to be used as such. These differences are important and takes a while to get used to, but will not be covered in detail in this guide. Instead, this guide explores some of the key concepts of game development in Flash, and outlines what the closest Defold equivalents are. Similarities and differences are discussed, along with common pitfalls, to enable you to get off to a running start in transitioning from Flash to Defold. ## Movie clips and game objects Movie clips are a key component of Flash game development. They are symbols, each containing a unique timeline. The closest equivalent concept in Defold is a game object. Unlike Flash movie clips, Defold game objects do not have timelines. Instead, a game object consists of multiple components. Components include sprites, sounds, and scripts---among many others (for further details about the components available see the [building blocks documentation](#manuals:building-blocks) and related articles). The game object in the screenshot below consists of a sprite and a script. The script component is used to control the behavior and look of game objects throughout the object’s lifecycle: While movie clips can contain other movie clips, game objects can not *contain* game objects. However, game objects can be *childed* to other game objects, creating hierarchies that can be moved, scaled or rotated in unison. ## Flash—manually creating movie clips In Flash, instances of movie clips can be added to your scene manually by dragging them from the library and onto the timeline. This is illustrated in the screenshot below, where each Flash logo is an instance of the "logo" movieclip: ## Defold—manually creating game objects As mentioned previously, Defold does not have a timeline concept. Instead, game objects are organized in collections. Collections are containers (or prefabs) that hold game objects and other collections. At the most basic level, a game can consist of only one collection. More frequently, Defold games make use of multiple collections, either added manually to the bootstrap “main” collection or dynamically loaded via [collection proxies](#manuals:collection-proxy). This concept of loading "levels" or "screens" does not have a direct Flash equivalent. In the example below, the "main" collection contains three instances (listed on the right, in the *Outline* window) of the "logo" game object (seen on the left, in the *Assets* browser window): ## Flash—referencing manually created movie clips Referring to manually created movie clips in Flash requires the use of a manually defined instance name: ## Defold—Game object id In Defold, all game objects and components are referred to via an address. In most cases only a simple name, or a shorthand is sufficient. For example: - `"."` addresses the current game object. - `"#"` addresses the current component (the script). - `"logo"` addresses the game object with the id "logo". - `"#script"` addresses the component with id "script" in the current game object. - `"logo#script"` addresses the component with id "script" in the game object with id "logo". The address of manually placed game objects is determined by the *Id* property assigned (see bottom right of screenshot). The id has to be unique for the current collection file you are working in. The editor automatically sets an id for you but you can change it for each game object instance that you create. You can find the id of a game object by running the following code in its script component: `print(go.get_id())`. This will print the id of the current game object in the console. The addressing model and message passing are key concepts in Defold game development. The [addressing manual](#manuals:addressing) and the [message passing manual](#manuals:message-passing) explains these in great detail. ## Flash—dynamically creating movie clips In order to dynamically create movie clips in Flash, ActionScript Linkage first needs to be set up: This creates a class (Logo in this case), which then enables instantiation of new instances of this class. Adding an instance of the Logo class to the Stage could be done as below: ```as var logo:Logo = new Logo(); addChild(logo); ``` ## Defold—creating game objects using factories In Defold, dynamic generation of game objects is achieved through the use of *factories*. Factories are components that are used to spawn copies of a specific game object. In this example, a factory has been created with the "logo" game object as a prototype: It is important to note that factories, like all components, need to be added to a game object before they can be used. In this example, we have created a game object called "factories", to hold our factory component: The function to call to generate an instance of the logo game object is: ```lua local logo_id = factory.create("factories#logo_factory") ``` The URL is a required parameter of `factory.create()`. In addition, you can add optional parameters to set position, rotation, properties, and scale. For more information on the factory component, please see the [factory manual](#manuals:factory). It is worth noting that calling `factory.create()` returns the id of the created game object. This id can be stored for later reference in a table (which is the Lua equivalent of an array). ## Flash—stage In Flash, we are familiar with the Timeline (top section of the screenshot below) and the Stage (visible below the Timeline): As discussed in the movie clips section above, the Stage is essentially the top level container of a Flash game and is created each time a project is exported. The Stage will by default have one child, the *`MainTimeline`*. Each movie clip generated in the project will have its own timeline, and can serve as a container for other symbols (including movie clips). ## Defold—collections The Defold equivalent of the Flash Stage is a collection. When the engine starts up it creates a new game world based on the content of a collection file. By default, this file is called "main.collection" but you can change which collection is loaded at startup by accessing the *game.project* settings file that is in the root of every Defold project: Collections are containers that are used in the editor to organize game objects and other collections. The contents of a collection can also be spawned via script into the runtime using a [collection factory](#manuals:collection-factory), which works the same way as a regular game object factory. This is useful for spawning groups of enemies, or a pattern of coin collectables, for instance. In the screenshot below, we have manually placed two instances of the "logos" collection into the "main" collection. In some cases, you want to load a completely new game world. The [collection proxy](#manuals:collection-proxy) component allows you to create a new game world based on the contents of a collection file. This would be useful for scenarios such as loading new game levels, mini games, or cutscenes. ## Flash—timeline The Flash timeline is primarily used for animation, using various frame by frame techniques or shape/motion tweens. The overall FPS (frames per second) setting of the project defines the length of time a frame is displayed. Advanced users can modify the overall FPS of the game, or even that of individual movie clips. Shape tweens allow the interpolation of vector graphics between two states. It is mostly only useful for simple shapes and applications, as the below example of shape tweening a square into a triangle demonstrates: Motion tweens allow the animation of various properties of an object, including size, position and rotation. In the example below, all the listed properties have been modified. ## Defold—property animation Defold works with pixel images as opposed to vector graphics, thus it does not have an equivalent for shape tweening. However, motion tweening has a powerful equivalent in [property animation](https://defold.com/ref/go/#go.animate). This is accomplished via script, using the `go.animate()` function. The go.animate() function tweens a property (such as color, scale, rotation or position) from the starting value to the desired end value, using one of many available easing functions (including custom ones). Where Flash required user implementation of more advanced easing functions, Defold includes [many easing functions](#manuals:animation) built-into the engine. Where Flash makes use of keyframes of graphics on a timeline for animation, one of the main methods of graphic animation in Defold is by flipbook animation of imported image sequences. Animations are organized in a game object component known as an atlas. In this instance we have an atlas for a game character with an animation sequence called "run". This consists of a series of png files: ## Flash—depth index In Flash, the display list determines what is shown and in what order. The ordering of objects in a container (such as the Stage) is handled by an index. Objects added to a container using the `addChild()` method will automatically occupy the top position of the index, starting from 0 and incrementing with each additional object. In the screenshot below, we have generated three instances of the "logo" movie clip: The positions in the display list are indicated by the numbers next to each logo instance. Ignoring any code to handle the x/y position of the movie clips, the above could have been generated like so: ```as var logo1:Logo = new Logo(); var logo2:Logo = new Logo(); var logo3:Logo = new Logo(); addChild(logo1); addChild(logo2); addChild(logo3); ``` Whether an object is displayed above or below another object is determined by their relative positions in the display list index. This is well illustrated by swapping the index positions of two objects, for instance: ```as swapChildren(logo2,logo3); ``` The result would look like the below (with the index position updated): ## Defold—z position The positions of game objects in Defold are represented by vectors consisting of three variables: x, y, and z. The z position determines the depth of a game object. In the default [render script](#manuals:render), the available z positions range from -1 to 1. Game objects with a z position outside the -1 to 1 range will not be rendered and therefore not visible. This is a common pitfall for developers new to Defold, and is worth keeping in mind if a game object is not visible when you expect it to be. Unlike in Flash where the editor only implies depth indexing (and allows modification using commands like *Bring Forward* and *Send Backward*), Defold allows you to set the z position of objects directly in the editor. In the screenshot below, you can see that "logo3" is displayed on top, and has a z position of 0.2. The other game objects have z positions of 0.0 and 0.1. Note that the z position of a game object nested in one or more collections is decided by its own z position, together with that of all its parents. For instance, imagine the logo game objects above were placed in a "logos" collection which in turn was placed in "main" (see screenshot below). If the "logos" collection had a z position of 0.9, the z positions of the game objects contained within would be 0.9, 1.0, and 1.1. Therefore, "logo3" would not be rendered as its z position is greater than 1. The z position of a game object can of course be changed using script. Assume the below is located in the script component of a game object: ```lua local pos = go.get_position() pos.z = 0.5 go.set_position(pos) ``` ## Flash `hitTestObject` and `hitTestPoint` collision detection Basic collision detection in Flash is achieved by using the `hitTestObject()` method. In this example, we have two movie clips: "bullet" and "bullseye". These are illustrated in the screenshot below. The blue boundary box is visible when selecting the symbols in the Flash editor, and it is these boundary boxes that drive the result of the `hitTestObject()` method. Collision detection using `hitTestObject()` is done as follows: ```as bullet.hitTestObject(bullseye); ``` Using the boundary boxes in this case would not be appropriate, as a hit would be registered in the scenario below: An alternative to `hitTestObject()` is the `hitTestPoint()` method. This method contains a `shapeFlag` parameter, which allows hit tests to be conducted against the actual pixels of an object as opposed to the bounding box. Collision detection using `hitTestPoint()` could be done as below: ```as bullseye.hitTestPoint(bullet.x, bullet.y, true); ``` This line would check the x and y position of the bullet (top left in this scenario) against the shape of the target. Since `hitTestPoint()` checks a point against a shape, which point (or points!) to check is a key consideration. ## Defold—collision objects Defold includes a physics engine that can detect collisions and let a script react to it. Collision detection in Defold starts with assigning collision object components to game objects. In the screenshot below, we have added a collision object to the "bullet" game object. The collision object is indicated as the red transparent box (which is visible in the editor only): Defold includes a modified version of the Box2D physics engine, which can simulate realistic collisions automatically. This guide assumes use of the kinematic collision objects, as these most closely resemble collision detection in Flash. Read more about the dynamic collision objects in the Defold [physics manual](#manuals:physics). The collision object includes the following properties: A box shape has been used as this was most appropriate for the bullet graphic. The other shape used for 2D collisions, sphere, will be used for the target. Setting the type to Kinematic means resolving collisions is done by your script as opposed to the built-in physics engine (for more information on the other types, please refer to the [physics manual](#manuals:physics)). The group and mask properties determine what collision group the object belongs to and what collision group it should be checked against, respectively. The current setup means a "bullet" can only collide with a "target". Imagine the setup was changed to the below: Now, bullets can collide with targets and other bullets. For reference, we have set up a collision object for the target that looks as follows: Note how the *Group* property is set to "target" and *Mask* is set to "bullet". In Flash, collision detection occurs only when explicitly called by the script. In Defold, collision detection occurs continuously in the background as long as a collision object remains enabled. When a collision occurs, messages are sent to all components of a game object (most relevantly, the script components). These are the [collision_response and contact_point_response](#manuals:physics-messages) messages, which contain all the information required to resolve the collision as desired. The advantage of Defold collision detection is that it is more advanced than that of Flash, with the ability to detect collisions between relatively complex shapes with very little setup effort. Collision detection is automatic, meaning looping through the various objects in the different collision groups and explicitly performing hit tests is not required. The main drawback is that there is no equivalent to the Flash `shapeFlag`. However, for most uses combinations of the basic box and sphere shapes suffice. For more complex scenarios, custom shapes [are possible](//forum.defold.com/t/does-defold-support-only-three-shapes-for-collision-solved/1985). ## Flash—event handling Event objects and their associated listeners are used to detect various events (e.g. mouse clicks, button presses, clips being loaded) and trigger actions in response. There are a variety of events to work with. ## Defold—call-back functions and messaging The Defold equivalent of the Flash event handling system consists of a few aspects. Firstly, each script component comes with a set of callback-functions that detect specific events. These are: init : Called when the script component is initialized. Equivalent to the constructor function in Flash. final : Called when the script component is destroyed (e.g. a spawned game object is removed). update : Called every frame. Equivalent to `enterFrame` in Flash. on_message : Called when the script component receives a message. on_input : Called when user input (e.g. mouse or keyboard) is sent to a game object with [input focus](https://defold.com/ref/go/#acquire_input_focus), which means that the object receives all input and can react to it. on_reload : Called when the script component is reloaded. The callback functions listed above are all optional and can be removed if not used. For details on how to set up input, please refer to the [input manual](#manuals:input). A common pitfall occurs when working with collection proxies - please refer to [this section](#manuals:input) of the input manual for more information. As discussed in the collision detection section, collision events are dealt with through the sending of messages to the game objects involved. Their respective script components receive the message in their on_message callback functions. ## Flash—button symbols Flash uses a dedicated symbol type for buttons. Buttons use specific event handler methods (e.g. `click` and `buttonDown`) to execute actions when user interaction is detected. The graphical shape of a button in the "Hit" section of the button symbol determines the hit area of the button. ## Defold—GUI scenes and scripts Defold does not include a native button component, nor can clicks be easily detected against the shape of a given game object in the way buttons are handled in Flash. The use of a [GUI](#manuals:gui) component is the most common solution, partially because the positions of the Defold GUI components are not affected by the in-game camera (if used). The GUI API also contains functions for detecting if user input like clicks and touch events are within the bounds of a GUI element. ## Debugging In Flash, the `trace()` command is your friend when debugging. The Defold equivalent is `print()`, and is used in the same way as `trace()`: ```lua print("Hello world!"") ``` You can print multiple variables using one `print()` function: ```lua print(score, health, ammo) ``` There is also a `pprint()` function (pretty print), which is useful when dealing with tables. This function prints the content of tables, including nested tables. Consider the script below: ```lua factions = {"red", "green", "blue"} world = {name = "Terra", teams = factions} pprint(world) ``` This contains a table (`factions`) nested in a table (`world`). Using the regular `print()` command would output the unique id of the table, but not the actual contents: ``` DEBUG:SCRIPT: table: 0x7ff95de63ce0 ``` Using the `pprint()` function as illustrated above gives more meaningful results: ``` DEBUG:SCRIPT: { name = Terra, teams = { 1 = red, 2 = green, 3 = blue, } } ``` If your game uses collision detection, you can toggle physics debugging by posting the message below: ```lua msg.post("@system:", "toggle_physics_debug") ``` Physics debug can also be enabled in the project settings. Before toggling physics debug our project would look like this: Toggling physics debug displays the collision objects added to our game objects: When collisions occur, the relevant collision objects light up. In addition, the collision vector is displayed: Finally, see the [profiler documentation](https://defold.com/ref/profiler/) for information on how to monitor CPU and memory usage. For more information on advanced debugging techniques, see the [debugging section](#manuals:debugging) in the Defold manual. ## Where to go from here - [Defold examples](https://defold.com/examples) - [Tutorials](/tutorials) - [Manuals](/manuals) - [Reference](https://defold.com/ref/go) - [FAQ](https://defold.com/faq/faq) If you have questions or get stuck, the [Defold forums](//forum.defold.com) are a great place to reach out for help. # Getting help {#manuals:getting-help} If you run into a problem while using Defold we'd like to hear from you so that we can fix the issue and/or help you work around the problem! There are several ways to discuss and also report issues. Chose the option that works best for you: ## Report a problem on the forum A good way to discuss and get help with a problem is to post a question on our [forum](https://forum.defold.com). Post either in the [Questions](https://forum.defold.com/c/questions) or [Bugs](https://forum.defold.com/c/bugs) category depending on the type of problem you have. Remember to [search](https://forum.defold.com/search) for your question/issue before asking as there may already be a solution to your problem. If you have several questions, create multiple posts. Do not ask unrelated questions in the same post. ### Required information We will not be able to provide support unless you provide the information needed: **Title** Make sure to use a short and descriptive title. A good title would be "How do I move a game object in the direction it is rotated?" or "How do I fade out a sprite?". A bad title would be "I need some help using Defold!" or "My game is not working!". **Describe the bug (REQUIRED)** A clear and concise description of what the bug is. **To Reproduce (REQUIRED)** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected behavior (REQUIRED)** A clear and concise description of what you expected to happen. **Defold version (REQUIRED):** - Version [e.g. 1.2.155] **Platforms (REQUIRED):** - Platforms: [e.g. iOS, Android, Windows, macOS, Linux, HTML5] - OS: [e.g. iOS8.1, Windows 10, High Sierra] - Device: [e.g. iPhone6] **Minimal reproduction case project (OPTIONAL):** Please attach a minimal project where the bug is reproduced. This will greatly help the person trying to investigate and fix the bug. **Logs (OPTIONAL):** Please provide relevant logs from engine, editor or build server. Learn where the logs are stored [here](#log-files). **Workaround (OPTIONAL):** If there is a workaround, please describe it here. **Screenshots (OPTIONAL):** If applicable, add screenshots to help explain your problem. **Additional context (OPTIONAL):** Add any other context about the problem here. ### Sharing code When you share code it is recommended to share the code as text, not as screenshots. Sharing it as text makes it easy to search, to highlight errors and to suggest and make modifications. Share code by wrapping it in three \`\`\` or indenting it with 4 spaces. Example: \`\`\` print("Hello code!") \`\`\` Result: ``` print("Hello code!") ``` ## Report a problem from the editor The editor provides a convenient way to report issues. Select the `Help->Report Issue` menu option from within the editor to report an issue. Selecting this menu option will bring you to an issue tracker on GitHub. Provide [log files](#log-files), information about your operating system, steps to reproduce the problem, possible workarounds etc. You need a GitHub account to submit a bug report this way. ## Discuss a problem on Discord If you run into a problem while using Defold you can try to ask the question on [Discord](https://www.defold.com/discord/). We do however recommend that complex questions and in-depth discussions are posted on the forum. Also note that we do not accept bug reports submitted through Discord. # Log files The engine, editor and build server generates logging information that can be very valuable when asking for help and debugging an issue. Always provide log files when reporting a problem: * [Engine logs](#manuals:debugging-game-and-system-logs) * [Editor logs](#manuals:editor#editor-logs) * [Build server logs](#manuals:extensions#build-server-logs) # Project setup {#manuals:project-setup} You can easily create a new project from within the Defold editor. You also have the option to open an existing project already located on your computer. ## Creating a new local project Click the `New Project` option and select what kind of project you would like to create. Specify a location on your hard drive where the project files will be stored. Click `Create New Project` to create the project in the location you've chosen. You can create a new project from a Template: Or from a Tutorial with step by step instructions: Or from a finished Sample game: ### Adding the project to GitHub A local project will have no integration with any version control system, meaning that the files reside only on your hard drive. Any changes you make to the files are permanent and there is no way to revert changes or recover deleted files. It is recommended to use a version control system such as Git to track changes to your files. This also makes it very easy to collaborate on a project with other people. Uploading a local project to GitHub can be done in just a few steps: 1. Create or login to an account on [GitHub](https://github.com/) 2. Create a repository using the [New Repository](https://help.github.com/en/articles/creating-a-new-repository) option 3. Upload all project files via the [Upload Files](https://help.github.com/en/articles/adding-a-file-to-a-repository) option The project is now under version control and you should [clone the project](https://help.github.com/en/articles/cloning-a-repository) to your local hard drive and work from this new location instead. ## Open an existing project Click the `Open From Disk` option to open a project already located on your computer. ## Open a recent project Once a project has been opened once it will show up in the list of recent projects. The list will show the projects you have worked on most recently and it will allow you to quickly open any of the projects by double-clicking the project in the list. # Project settings {#manuals:project-settings} The file *game.project* contains all project wide settings. It must stay in the root folder of the project and must be named *game.project*. The first thing the engine does when starting up and launching your game is look for this file. Every setting in the file belongs to a category. When you open the file Defold presents all settings grouped by category. ## File format The settings in *game.project* are usually changed from within Defold, but the file can also be edited in any standard text editor. The file follows the INI file format standard and looks like this: ```ini [category1] setting1 = value setting2 = value [category2] ... ``` A real example is: ```ini [bootstrap] main_collection = /main/main.collectionc ``` which means that the setting *main_collection* belongs to the *bootstrap* category. Whenever a file reference is used, like the example above, the path needs to be appended with a 'c' character, which means you're referencing the compiled version of the file. Also note that the folder containing *game.project* will be the project root, which is why there is an initial '/' in the setting path. ## Runtime access It is possible to read any value from *game.project* at runtime using [`sys.get_config_string(key)`](https://defold.com/ref/sys/#sys.get_config_string), [`sys.get_config_number(key)`](https://defold.com/ref/sys/#sys.get_config_number) and [`sys.get_config_int(key)`](https://defold.com/ref/sys/#sys.get_config_int). Examples: ```lua local title = sys.get_config_string("project.title") local gravity_y = sys.get_config_number("physics.gravity_y") ``` The key is a combination of the category and setting name, separated by a dot, and written in lowercase letters with any space characters replaced by underscores. Examples: The field "Title" from the "Project" category becomes `project.title` and the "Gravity Y" field from the "Physics" category becomes `physics.gravity_y`. ## Sections and settings Below are all the available settings, arranged by category. ### Project #### Title The title of the application. #### Version The version of the application. #### Publisher Publisher name. #### Developer Developer name. #### Write Log File Controls when the engine writes a log file. Options: - "Never": Do not write a log file. - "Debug": Write a log file only for Debug builds. - "Always": Write a log file for both Debug and Release builds. If running more than one instance from the editor the file will be named *instance_2_log.txt* with `2` being the instance index. If running a single instance or from a bundle the file will be named *log.txt*. The location of the log file will be one of the following paths (tried in order): 1. The path specified in *project.log_dir* (hidden setting) 2. The system log path: * macOS/iOS: `NSDocumentDirectory` * Android: `Context.getExternalFilesDir()` * Others: Application root 3. The application support path * macOS/iOS: `NSApplicationSupportDirectory` * Windows: `CSIDL_APPDATA` (e.g. `C:\Users\\AppData\Roaming`) * Android: `Context.getFilesDir()` * Linux: `HOME` environment variable #### Minimum Log Level Specify the minimum log level for the logging system. Only logs at or above this level will be shown. #### Compress Archive Enables compression of archives when bundling. Note that this currently applies to all platforms except Android where the apk already contains all data compressed. #### Dependencies A list of URLs to the project *Library URL*s. Refer to the [Libraries manual](#manuals:libraries) for more information. #### Custom Resources `custom_resources` Custom resources are bundled in the main game archive using the [*Custom Resources* field](#manuals:project-settings) in *game.project*. The *Custom Resources* field should contain a comma separated list of resources that will be included in the main game archive. If directories are specified, all files and directories in that directory are recursively included. You can read the files using [`sys.load_resource()`](https://defold.com/ref/sys/#sys.load_resource). Loading custom resources is covered in more detail in the [File Access manual](#manuals:file-access). #### Bundle Resources `bundle_resources` Bundle resources are additional files and folders located as a part of your application bundle using the [*Bundle Resources* field](#manuals:project-settings) in *game.project*. The *Bundle Resources* field should contain a comma separated list of directories containing resource files and folders that should be copied as-is into the resulting package when bundling. The directories must be specified with an absolute path from the project root, for example `/res`. The resource directory must contain subfolders named by `platform`, or `architecture-platform`. Supported platforms are `ios`, `android`, `osx`, `win32`, `linux`, `web`, `switch` A subfolder named `common` is also allowed, containing resource files common for all platforms. Example: ``` res ├── win32 │ └── mywin32file.txt ├── common │ └── mycommonfile.txt └── android ├── myandroidfile.txt └── res └── xml └── filepaths.xml ``` You can use [`sys.get_application_path()`](https://defold.com/ref/stable/sys/#sys.get_application_path:) to get the path to where the application is stored. Use this application base path to create the final absolute path to the files you need access to. Once you have the absolute path of these files you can use the `io.*` and `os.*` functions to access the files. Loading bundle resources is covered in more detail in the [File Access manual](#manuals:file-access). #### Bundle Exclude Resources `bundle_exclude_resources` A comma separated list of resources that should not be included in the bundle. That is, they're removed from the result of the collection of the `bundle_resources` step. ### Library #### Include Dirs A space separated list of directories that should be shared from your project via library sharing. Refer to the [Libraries manual](#manuals:libraries) for more information. ### Engine #### Run While Iconified Allow the engine to continue running while the application window is iconified (desktop platforms only). #### Fixed Update Frequency The update frequency of the `fixed_update(self, dt)` lifecycle function. In Hertz. #### Max Time Step If the time step becomes too large during a single frame, it will be capped to this max value. Seconds. ### Render #### Clear Color Red Clear color red channel, used by the render script and when the window is created. #### Clear Color Green Clear color green channel, used by the render script and when the window is created. #### Clear Color Blue Clear color blue channel, used by the render script and when the window is created. #### Clear Color Alpha Clear color alpha channel, used by the render script and when the window is created. ### Physics #### Max Collision Object Count Max number of collision objects. #### Type Which type of physics to use, `2D` or `3D`. #### Gravity X World gravity along x-axis. In meters per second. #### Gravity Y World gravity along y-axis. In meters per second. #### Gravity Z World gravity along z-axis. In meters per second. #### Debug Check if physics should be visualized for debugging. #### Debug Alpha Alpha component value for visualized physics, `0`--`1`. #### World Count Max number of concurrent physics worlds, `4` by default. If you load more than 4 worlds simultaneously through collection proxies you need to increase this value. Be aware that each physics world allocates a fair amount of memory. #### Scale Tells the physics engine how to scale the physics worlds in relation to the game world for numerical precision, `0.01`--`1.0`. If the value is set to `0.02`, it means that the physics engine will view 50 units as 1 meter ($1 / 0.02$). #### Allow Dynamic Transforms Check if the physics engine should apply the transform of a game object to any attached collision object components. This can be used to move, scale and rotate collision shapes, even those that are dynamic. #### Use Fixed Timestep Check if the physics engine should use fixed and framerate independent updates. Use this setting in combination with the `fixed_update(self, dt)` lifecycle function and the `engine.fixed_update_frequency` project setting to interact with the physics engine at regular intervals. For new projects the recommended setting is `true`. #### Debug Scale How big to draw unit objects in physics, like triads and normals. #### Max Collisions How many collisions that will be reported back to the scripts. #### Max Contacts How many contact points that will be reported back to the scripts. #### Contact Impulse Limit Ignore contact impulses with values less than this setting. #### Ray Cast Limit 2d The max number of 2d ray cast requests per frame. #### Ray Cast Limit 3d The max number of 3d ray cast requests per frame. #### Trigger Overlap Capacity The maximum number of overlapping physics triggers. #### Velocity Threshold Minimum velocity that will result in elastic collisions. #### Max Fixed Timesteps Max number of steps in the simulation when using fixed timestep (3D only). ### Shader #### Exclude GLES 2.0 Don't compile shaders for devices running OpenGLES 2.0 / WebGL 1.0. ### Resource #### Http Cache If checked, a HTTP cache is enabled for faster loading of resources over the network to the running engine on device. #### Uri Where to find the project build data, in URI format. #### Max Resources The max number of resources that can be loaded at the same time. ### Collection #### Max Instances Max number of game object instances in a collection, `1024` by default. [(See information about component max count optimizations)](#component-max-count-optimizations). #### Max Input Stack Entries Max number of game objects in the input stack. ### Sprite #### Max Count Max number of sprites per collection. [(See information about component max count optimizations)](#component-max-count-optimizations). #### Subpixels Check to allow sprites to appear unaligned with respect to pixels. ### Spine #### Max Count Max number of spine model components. [(See information about component max count optimizations)](#component-max-count-optimizations). ### Model #### Max Count Max number of model components per collection. [(See information about component max count optimizations)](#component-max-count-optimizations). #### Split Meshes Split meshes with more than 65536 vertices into new meshes. #### Max Bone Matrix Texture Width Maximum width of the bone matrix texture. Only the size needed for animations is used, rounded up to nearest power-of-two. #### Max Bone Matrix Texture Height Maximum height of the bone matrix texture. Only the size needed for animations is used, rounded up to nearest power-of-two. ### Label #### Max Count Max number of labels. [(See information about component max count optimizations)](#component-max-count-optimizations). #### Subpixels Check to allow labels to appear unaligned with respect to pixels. ### Box2D #### Velocity Iterations Number of velocity iterations for the Box2D 2.2 physics solver. #### Position Iterations Number of position iterations for the Box2D 2.2 physics solver. #### Sub Step Count Number of sub-steps for the Box2D 3.x physics solver. ### Collection factory #### Max Count Max number of collection factories. [(See information about component max count optimizations)](#component-max-count-optimizations). ### iOS #### App Icon 57x57--180x180 Image file (.png) to use as application icon at given width and height dimensions `W` × `H`. #### Launch Screen Storyboard file (.storyboard). Learn more about how to create one in the [iOS manual](#manuals:ios). #### Icons Asset The icons asset file (.car) containing app icons. #### Prerendered Icons (iOS 6 and earlier) Check if your icons are prerendered. If this is unchecked the icons will get a glossy highlight added automatically. #### Bundle Identifier The bundle identifier lets iOS recognize any updates to your app. Your bundle ID must be registered with Apple and be unique to your app. You cannot use the same identifier for both iOS and macOS apps. Must consist of two or more segments separated by a dot. Each segment must start with a letter. Each segment must only consist of alphanumeric letters, the underscore or hyphen (-) character (see [`CFBundleIdentifier`](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-130430)) #### Bundle Name The bundle short name (15 characters) (see [`CFBundleName`](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-130430)). #### Bundle Version The bundle version, either a number or x.y.z. (see [`CFBundleVersion`](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-130430)) #### Info.plist If specified, use this *`info.plist`* file when bundling your app. #### Privacy Manifest The Apple Privacy Manifest for the application. The field will default to `/builtins/manifests/ios/PrivacyInfo.xcprivacy`. #### Custom Entitlements If specified, the entitlements in the supplied provisioning profile (`.entitlements`, `.xcent`, `.plist`) will be merged with the entitlements from the provisioning profile supplied when bundling the application. #### Default Language The language used if the application doesn't have user's preferred language in `Localizations` list (see [`CFBundleDevelopmentRegion`](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-130430)). Use the two-letter ISO 639-1 standard if preferred language is available there or the three-letter ISO 639-2. #### Localizations This field contains comma-separated strings identifying the language name or ISO language designator of the supported localizations (see [`CFBundleLocalizations`](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-109552)). ### macOS #### App Icon Bundle icon file (.icns) to use as application icon on macOS. #### Info.plist If set, use the specified info.plist file when bundling. #### Privacy Manifest The Apple Privacy Manifest for the application. The field will default to `/builtins/manifests/osx/PrivacyInfo.xcprivacy`. #### Bundle Identifier The bundle identifier lets macOS recognize updates to your app. Your bundle ID must be registered with Apple and be unique to your app. You cannot use the same identifier for both iOS and macOS apps. Must consist of two or more segments separated by a dot. Each segment must start with a letter. Each segment must only consist of alphanumeric letters, the underscore or hyphen (-) character. #### Default Language The language used if the application doesn't have user's preferred language in `Localizations` list (see [`CFBundleDevelopmentRegion`](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-130430)). Use the two-letter ISO 639-1 standard if preferred language is available there or the three-letter ISO 639-2. #### Localizations This field contains comma-separated strings identifying the language name or ISO language designator of the supported localizations (see [`CFBundleLocalizations`](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-109552)). ### HTML5 Refer to the [HTML5 platform manual](#manuals:html5) for more information about many of these options. #### Heap Size Heap size in megabytes for Emscripten to use. #### .html Shell Use the specified template HTML file when bundling. By default `/builtins/manifests/web/engine_template.html`. #### Custom .css Use the specified theme CSS file when bundling. By default `/builtins/manifests/web/light_theme.css`. #### Splash Image If set, use the specified splash image on startup when bundling instead of Defold logo. #### Archive Location Prefix When bundling for HTML5 game data is split up into one or more archive data files. When the engine starts the game, these archive files are read into memory. Use this setting to specify the location of the data. #### Archive Location Suffix Suffix to be appended to the archive files. Useful to, for instance, force non-cached content from a CDN (`?version2` for example). #### Engine Arguments List of arguments that will be passed to the engine. #### Wasm Streaming Enable streaming of the wasm file (faster and uses less memory, but requires the `application/wasm` MIME type). #### Show Fullscreen Button Enables Fullscreen Button in `index.html` file. #### Show Made With Defold Enables Made With Defold link in `index.html` file. #### Show Console Banner When enabled this option will print information about the engine and engine version in the browser console (using `console.log()`) when the engine starts. #### Scale Mode Specifies which method to use to scale the game canvas. #### Retry Count The number of attempts to download a file when the engine starts (see `Retry Time`). #### Retry Time The number of seconds to wait between attempts to download a file when the download failed (see `Retry Count`). #### Transparent Graphics Context Check if you want the graphics context to have a transparent backdrop. ### Live update #### Settings Liveupdate settings resource file to use during bundling. #### Mount On Start Enables auto-mount of previously mounted resources when the application starts. ### Profiler #### Enabled Enable the in-game profiler. #### Track Cpu If checked, enable CPU profiling in release versions of the builds. Normally, you can only access profiling information in debug builds. #### Sleep Between Server Updates Number of milliseconds to sleep between server updates. #### Performance Timeline Enabled Enable in-browser performance timeline (HTML5 only). --- ## Setting config values on engine startup When the engine starts, it is possible to provide config values from the command line that override the *game.project* settings: ```bash # Specify a bootstrap collection $ dmengine --config=bootstrap.main_collection=/my.collectionc # Set two custom config values $ dmengine --config=test.my_value=4711 --config=test2.my_value2=foobar ``` Custom values can---just like any other config value---be read with [`sys.get_config_string()`](https://defold.com/ref/sys/#sys.get_config_string) or [`sys.get_config_number()`](https://defold.com/ref/sys/#sys.get_config_number): ```lua local my_value = sys.get_config_number("test.my_value") local my_value2 = sys.get_config_string("test.my_value2") ``` ## Component max count optimizations The *game.project* settings file contains many values specifying the maximum number of a certain resource that can exist at the same time, often counted per loaded collection (also called world). The Defold engine will use these max values to preallocate memory for this amount of memory to avoid dynamic allocations and memory fragmentation while the game is running. The Defold data structures used to represent components and other resources are optimized to use as little memory as possible but care should still be taken when setting the values to avoid allocating more memory than is actually necessary. To further optimize memory usage the Defold build process will analyse the content of the game and override the max counts if it is possible to know for certain the exact amount: * If a collection doesn't contain any factory components the exact amount of each component and Game Object will be allocated and the max count values will be ignored. * If a collection contains a factory component the spawned objects will be analysed and the max count will be used for components that can be spawned from the factories and for Game Objects. * If a collection contains a factory or a collection factory with activated "Dynamic Prototype" option, this collection will use the max counters. ## Custom project settings It is possible to define custom settings for the main project or for a [native extension](#manuals:extensions). Custom settings for the main project must be defined in a `game.properties` file in the root of the project. For a native extension they should be defined in an `ext.properties` file next to the `ext.manifest` file. The settings file uses the same INI format as *game.project* and property attributes are defined using a dot notation with a suffix: ``` [my_category] my_property.private = 1 ... ``` The default meta file that is always applied is available [here](https://github.com/defold/defold/blob/dev/com.dynamo.cr/com.dynamo.cr.bob/src/com/dynamo/bob/meta.properties) The following attributes are currently available: ``` [my_extension] // `type` - used for the value string parsing my_property.type = string // one of the following values: bool, string, number, integer, string_array, resource // `help` - used as help tip in the editor (not used for now) my_property.help = string // `default` - value used as default if user didn't set value manually my_property.default = string // `private` - private value used during the bundle process but will be removed from the bundle itself my_property.private = 1 // boolean value 1 or 0 // `label` - editor input label my_property.label = My Awesome Property // `minimum` and/or `maximum` - valid range for numeric properties, validated in the editor UI my_property.minimum = 0 my_property.maximum = 255 // `options` - drop-down choices for the editor UI, comma-separated value[:label] pairs my_property.options = android: Android, ios: iOS // `resource` type only: my_property.filter = jpg,png // allowed file extensions for resource selector dialog my_property.preserve-extension = 1 // use original resource extension instead of a built one // deprecation my_property.deprecated = 1 // mark property as deprecated my_property.severity-default = warning // if deprecated property is specified, but set to a default value my_property.severity-override = error // if deprecated property is specified and set to a non-default value ``` Additionally, you can set the following attributes on a setting category: ``` [my_extension] // `group` - game.project category group, e.g. Main, Platforms, Components, Runtime, Distribution group = Runtime // `title` - displayed category title title = My Awesome Extension // `help` - displayed category help help = Settings for My Awesome Extension ``` At the moment meta properties are used only in `bob.jar` when bundling application, but later will be parsed by the editor and represented in the *game.project* viewer. # Libraries {#manuals:libraries} The Libraries feature allows you to share assets between projects. It is a simple but very powerful mechanism that you can use in your workflow in a number of ways. Libraries are useful for the following purposes: * To copy assets from a finished project to a new one. If you are making a sequel to an earlier game, this is an easy way to get going. * To build a library of templates that you can copy into you projects and then customize or specialize. * To build one or more libraries of ready-made objects or scripts that you can reference directly. This is very handy for storing common script modules or to build a shared library of graphics, sound and animation assets. ## Setting up library sharing Suppose you want to build a library containing shared sprites and tile sources. You start by [setting up a new project](#manuals:project-setup). Decide what folders you want to share from the project and add the names of those folders to the *`include_dirs`* property in the Project settings. If you want to list more than one folder, separate the names with spaces: Before we can add this library to another project we need a way to locate the library. ## Library URL Libraries are referred to via a standard URL. For a project hosted on GitHub it would be the URL to a project release: It is recommend to always depend on a specific release of a library project instead of on the master branch. This way it is up to you as a developer to decide when to incorporate changes from a library project as opposed to always getting the latest (and potentially breaking) changes from the master branch of a library project. It is recommended to always review third-party libraries before use. Learn more [securing your use of third-party software](#manuals:application-security). ### Basic access authentication It is possible to add a username and password/token to the library URL to perform basic access authentication when using libraries that are not publicly available: ``` https://username:password@github.com/defold/private/archive/main.zip ``` The `username` and `password` fields will be extracted and added as an `Authorization` request header. This works for any server which supports basic access authorization. Make sure to not share or accidentally leak your generated personal access token or password as it can have dire consequences if they fall into the wrong hands! To avoid accidentally leaking any credentials by having them in clear text in the library URL it is also possible to use a string replacement pattern and store the credentials as environment variables: ``` https://__PRIVATE_USERNAME__:__PRIVATE_TOKEN__@github.com/defold/private/archive/main.zip ``` In the above example the username and token will be read from the system environment variables `PRIVATE_USERNAME` and `PRIVATE_TOKEN`. #### GitHub authentication To fetch from a private repository on GitHub you need to [generate a personal access token](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token) and use that as your password. ``` https://github-username:personal-access-token@github.com/defold/private/archive/main.zip ``` #### GitLab authentication To fetch from a private repository on GitLab you need to [generate a personal access token](https://docs.gitlab.com/ee/security/token_overview.html) and send as a URL parameter. ``` https://gitlab.com/defold/private/-/archive/main/test-main.zip?private_token=personal-access-token ``` ### Advanced access authentication When using the basic access authentication a user's access token and username will be shared on any repository used for the project. With a greater than 1 man team this can be an issue. To solve this issue a "read only" user needs to be used for library access to the repository, on GitHub this requires an organization, a team and a user who doesn't need to edit the repo (hence read only). GitHub Steps: * [Create an organisation](https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/creating-a-new-organization-from-scratch) * [Create a team within the organisation](https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/creating-a-team) * [Transfer the desired private repository to your organisation](https://docs.github.com/en/github/administering-a-repository/transferring-a-repository) * [Give the team "read only" access to the repository](https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/managing-team-access-to-an-organization-repository) * [Create or select a user to be part of this team](https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/organizing-members-into-teams) * Use the "basic access authentication" above to create a personal access token for this user At this point the new user's authentication details can be committed and pushed to the repository. This will allow anyone working with your private repository to fetch it as a library without having edit permissions to the library itself. The read only user's token is fully accessible to anyone who can access the game repositories that are using the library. This solution was proposed on the Defold forum and [discussed in this thread](https://forum.defold.com/t/private-github-for-library-solved/67240). ## Setting up library dependencies Open the project that you would like to access the library from. In the project settings, add the Library URL to the *dependencies* property. You can specify multiple dependent projects if you want. Just add them one by one using the `+` button and remove using the `-` button: Now, select `Project ▸ Fetch Libraries` to update library dependencies. This happens automatically whenever you open a project so you will only need to do this if the dependencies change without re-opening the project. This happens if you add or remove dependency libraries or if one of the dependency library projects is changed and synchronized by someone. Now the folders that you shared appear in the *Assets pane* and you can use everything you shared. Any synchronized changes done to the library project will be available in your project. ## Editing Files in Library Dependencies Files in libraries cannot be saved. You can make changes, and the editor will be able to build with those changes, which is useful for testing. However, the file itself remains unchanged, and all modifications will be discarded when the file is closed. If you want to make changes to library files, make sure to create your own fork of the library and make changes there. Another option is to copy/paste the entire library folder into your project directory and use the local copy. In this case, your local folder will shadow the original dependency, and the dependency link should be removed from `game.project` (don’t forget to choose `Project ▸ Fetch Libraries` afterward). `builtins` is also a library provided by the engine. If you want to edit files there, make sure to copy them into your project and use those instead of the original `builtins` files. For example, to modify `default.render_script`, copy both `/builtins/render/default.render` and `/builtins/render/default.render_script` into your project folder as `my_custom.render` and `my_custom.render_script`. Then, update your local `my_custom.render` to reference the `my_custom.render_script` instead of the built-in one, and set your custom `my_custom.render` in `game.project` under the Render setting. If you copy-paste a material and want to use it across all components of a certain type, it might be useful to use [per-project templates](#manuals:editor). ## Broken references Library sharing only includes files that are located under the shared folder(s). If you create something that references assets that are located outside of the shared hierarchy, the reference paths will be broken. ## Name collisions Since you can list several project URLs in the *dependencies* project setting you might encounter a name collision. This happens if two or more of the dependent projects share a folder with the same name in the *`include_dirs`* project setting. Defold resolves name collisions by simply ignoring all but the last reference to folders of the same name in the order the project URLs are specified in the *dependencies* list. For instance. If you list 3 library project URLs in the dependencies and all of them share a folder named *items*, only one *items* folder will show up---the one belonging to the project that is last in the URL list. # Ignoring files {#manuals:project-defignore} It is possible to configure the Defold editor and tools to ignore files and folders in a project. This can be useful if the project contains files with file extensions which conflict with file extensions used by Defold. One such example is Go language files with the .go file extension which is the same as the editor uses for game object files. ## The `.defignore` file The files and folders to exclude are defined in a file named `.defignore` in the project root. The file should list files and folders to exclude, one per line. Example: ``` /path/to/file.png /otherpath ``` This will exclude the file `/path/to/file.png` and anything in the path `/otherpath`. ## The `.defunload` file For certain large projects that contain multiple independent modules, you may want to exclude parts of it from loading to reduce memory usage and load times in the editor. To achieve this, you can list paths to exclude from loading in a `.defunload` file below the project directory. Simply put, the `.defunload` file allows you to hide parts of the project from the editor without making it a build error to reference the hidden resources. The patterns in `.defunload` use the same rules as the `.defignore` file. Unloaded Collections and Game Objects will behave as if they were empty when referenced by loaded resources. Other resources that match `.defunload` patterns will be in an unloaded state, and cannot be viewed in the editor. However, if a resource that is loaded depends on them, the unloaded resources and their dependencies are loaded automatically. For example, if a Sprite depends on images in an Atlas, we have to load the Atlas, or the missing image will be reported as an error. If this happens, a notification will warn the user about the situation and provide information about which unloaded resource was referenced from where. The editor will prevent the user from adding references to `.defunloaded` resources from loaded resources, so this situation only occurs when resources are read from disk. Contrary to the `.defignore` file, you need to restart the editor after you edit the `.defunload` file to see the changes take effect. # Editor overview {#manuals:editor} The editor allows you to browse and manipulate all files and folders in your game project in an efficient manner. Editing files brings up a suitable editor and shows all relevant information about the file in separate views. ## Starting the Editor When you run the Defold Editor, you are presented with a project selection and creation screen. Click to select what you want to do: MY PROJECTS : Here are your recently opened projects so you can quickly access them. This is the default view of the starting screen. If you didn't open any projects earlier (or removed all), it will show two buttons - you can click `Open From Disk…` to find and open one using system file browser or click `Create New Project` button and it will switch to a tab `TEMPLATES`. If you have earlier opened projects, it will show a list of your projects, like on the picture below: TEMPLATES : Contains empty or almost empty basic projects made for quick start of a new Defold project for certain platforms or using certain extensions. TUTORIALS : Contains projects with guided tutorials to learn, play and modify, if you would like to follow a tutorial. SAMPLES : Contains projects prepared to showcase certain use cases. When you create a new project it is stored on your local drive and any edits you do are saved locally. You can learn more about the different options in the [Project Setup manual](#manuals:project-setup). ## Editor Language In the bottom left corner of the starting screen you can see a Language selection - select from the available currently localizations (since Defold 1.11.2). This is also available in the Editor in `File ▸ Preferences ▸ General ▸ Editor Language`. ## The Editor panes The Defold Editor is separated into a set of panes, or views, that display specific information. ### 1. Assets pane Lists all the files and folders that are part of your project in a tree structure, corresponding to the same structure on your disk. Click and scroll to navigate the list. All file oriented operations can be made in this view: - `Left Mouse Click` to select any file or folder, and while holding `⇧ Shift` you can expand selection or while holding `Ctrl`/`⌘ Cmd` you can (un)select clicked. - `Double Mouse Click` a file to open it in a specific editor for that file type. - `Drag and Drop` to add files from elsewhere on your disk to the project or move files and folders to new locations in the project. - `Right Mouse Click` to open a _Context Menu_ from where you can create new files or folders, rename, delete, track file dependencies and more. ### 2. Scene Editor pane Double-clicking a collection, game object, or visual component file opens the *Scene Editor* — the visual editor for building and editing scenes. Script files and other non-visual resources open in their own dedicated editors instead. Some of the core features offered by the Scene Editor: - [2D and 3D scene navigation](#manuals:scene-editing) with orthographic and perspective camera modes - [Transform tools](#manuals:scene-editing) for moving, rotating and scaling objects - [Free Camera Mode](#manuals:scene-editing) for first-person 3D navigation - [Grid settings](#manuals:scene-editing) with configurable size, plane and appearance - [Visibility filters](#manuals:scene-editing) to toggle component types and guides Read more in the [Scene Editor manual](#manuals:scene-editing). ### 3. Outline pane This view shows the content of the file currently being edited, but in a hierarchical tree structure. The Outline reflects the editor view and allows you to perform operations on your items: - `Left Mouse Click` to select an item, and while holding `⇧ Shift` you can expand selection or while holding `Ctrl`/`⌘ Cmd` you can (un)select clicked. - `Drag and drop` to move items. Drop a game object on another game object in a collection to create a parent-child relationship. - `Right Mouse Click` to open a _Context Menu_ from where you can add items, delete selected items etc. It is possible to toggle the visibility of game objects and visual components by clicking on the little `👁` Eye Icon to the right of an element in the list (Defold 1.9.8 and newer). ### 4. Properties pane This view shows properties associated with the currently selected item, like Id, URL, Position, Rotation, Scale, and/or other component specific properties and also custom properties for scripts. You can also `Drag` the `↕` Up-Down Arrow and move mouse to change value of the given numerical property (1.10.2+). ### 5. Tools pane This view has several tabs. *Console* tab : shows any error, warning and info engine output or purposeful printing that you do while your game is running, *Build Errors* : shows errors from the building process, *Search Results* : shows results of searching (`Ctrl`/`⌘ Cmd` + `Shift` + `F`) the whole project, if you click `Keep Results` *Curve Editor* : used when editing curves in the [Particle Editor](#manuals:particlefx). The Tools pane is also used for interacting with the integrated debugger. Read more about it in the [Debugging Manual](#manuals:debugging). ### 6. Changed Files pane If your project uses the distributed version-control system Git this view lists any files that has been changed, added or deleted in your project. By synchronizing the project regularly you can bring your local copy in sync with what is stored in the project Git repository, that way you can collaborate within a team, and you won’t lose your work if disaster strikes. You can learn more about Git in our [Version Control manual](#manuals:version-control). Some file oriented operations can be performed in this view: - `Left Mouse Click` - to select a given file, and while holding `⇧ Shift` you can expand selection or while holding `Ctrl`/`⌘ Cmd` you can (un)select clicked. If a single changed file is selected you can click `Diff` to show the differences. You can click `Revert` to undo changes in all selected files. - `Double Left Mouse Click` a file to open a view of the file. The editor opens the file in a suitable editor, just like in the assets view. - `Right Mouse Click` a file to open a pop up menu from where you can open a diff view, revert all changes done to the file, find the file on the filesystem and more. ### Menu Bar On the top of the Editor view or in System Bar on Mac you can find Menu Bar with 6 menus: `File`, `Edit`, `View`, `Project`, `Debug`, `Help`. Their functions will be explained in the manuals. ### Status Bar On the bottom bar of the Editor you can find a narrow space in which the Status is displayed, e.g.: - when a new update is available a clickable button `Update Available` will be visible - check section Updating the Editor in this manual below. - when building or bundling a progress of it will be presented there. ## Panes Size and Visibility Panes size can be adjusted inside the Editor by `Dragging` the section borders between all described above 6 Panes. Panes visibility can be toggled in the Editor by using options in `View` menu or using given shortcuts: - `Toggle Assets Pane` (`F6`) to toggle Assets and Changed Files Panes visibility - `Toggle Changed Files` to toggle visibility of the Changed Files Pane alone - `Toggle Tools Pane` (`F7`) to toggle Tools Pane visibility - `Toggle Properties Pane` (`F8`) to toggle Outline and Properties Panes visibility In the `View` menu you can also toggle or change other visibility related settings, like Grid, Guides, Camera or fit the view to selection (`Frame Selection` or `F` key) and toggle between default 2D and 3D view (`Realign Camera` or `.` key), many of them accessible from the Toolbar or via shortcuts too. ## Tabs If you have multiple files open, a separate tab for each file is shown at the top of the Editor view. Tabs in a single pane can be moved around - `Drag and Drop` them to swap their positions inside the tabs bar. You can also: - `Right Mouse Click` on a tab to open a _Context Menu_, - Click `Close` (`Ctrl`/`⌘ Cmd` + `W`) a single tab, - Click `Close Others` to close all tabs except the selected one, - Click `Close All` (`Ctrl`/`⌘ Cmd` + `Shift`+`W`) to close all tabs in the active pane, - Select `➝| Open As` - to use other than default editor or associated external tool set in `File ▸ Preferences ▸ Code ▸ Custom Editor`. Check more in [Preferences manual](#manuals:editor-preferences). ## Side-by-side editing It is possible to open 2 editor views side by side. - `Right Mouse Click` the tab for the editor you want to move and select `Move to Other Tab Pane`. You can also use the tab menu to `Swap with Other Tab Pane` to move given tab between panes or `Join Tab Panes` to a single pane. ## Creating new project files To create new resource files, either select `File ▸ New…` and then choose the file type from the menu, or use the context menu: `Right Mouse Click` the target location in the `Assets` browser, then select `New… ▸ [file type]`: Type a suitable *Name* for the new file and eventually change *Location*. The full file name including the file type suffix is shown under *Preview* in the dialog: ## Templates It is possible to specify custom templates for each project. To do so, create a new folder named `templates` in the project’s root directory, and add new files named `default.*` with the desired extensions, such as `/templates/default.gui` or `/templates/default.script`. Additionally, if the `{% raw %}{{NAME}}{% endraw %}` token is used in these files, it will be replaced with the filename specified in the file creation window. If a template is available for a given file type, whenever a new file of this type is created, it will be initialized with the content of the file from `templates`. ## Importing files to your project To add asset files (images, sounds, models etc) to your project, simply drag and drop them to the correct position in the *Assets* browser. This will make _copies_ of the files at the selected location in the project file structure. Read more about [how to import assets in our manual](#manuals:importing-assets). ## Updating the Editor The Editor will automatically check for updates when connected to internet. When an update is detected a blue clickable link `Update Available` will be shown in the lower left corner of the project selection screen or in the lower right corner of the Editor window. Press the `Update Available` clickable link to download and update. A confirmation window with information will pop up - click `Download Update` to proceed. You will see the download progress in the bottom status bar: After update is downloaded the blue link will change to `Restart to Update`. Click it to restart and open the updated Editor. ## Preferences You can modify the settings of the Editor in the `Preferences` window. To open it click `File ▸ Preferences…` or shortcut `Ctrl`/`⌘ Cmd` + `,` Read more details in the [Preferences manual](#manuals:editor-preferences) ## Editor Logs If you run into a problem with the Editor and need to report issue (`Help ▸ Report Issue`) it is a good idea to provide log files from the editor itself. To open location of the logs in your system browser click on `Help ▸ Show Logs`. Read more in [Getting Help manual](#manuals:getting-help). The editor logs files can be found here: * Windows: `C:\Users\ **Your Username** \AppData\Local\Defold` * macOS: `/Users/ **Your Username** /Library/Application Support/` or `~/Library/Application Support/Defold` * Linux: `$XDG_STATE_HOME/Defold` or `~/.local/state/Defold` You can also get access to editor logs while the Editor is running if it is started from a terminal/command prompt. To launch the Editor use command: ```shell # Linux: $ ./path/to/Defold/Defold # macOS: $ > ./path/to/Defold.app/Contents/MacOS/Defold ``` ## Editor Server When the Editor opens a project, it will start a web server on a random port. The server may be used to interact with the editor from other applications. Since 1.11.0, the port is written to the `.internal/editor.port` file. Additionally, since 1.11.0 the editor executable has a command line option `--port` (or `-p`), which allows specifying the port during launch, e.g.:: ```shell # Windows .\path\to\Defold\Defold.exe --port 8181 # Linux: ./path/to/Defold/Defold --port 8181 # macOS: ./path/to/Defold/Defold.app/Contents/MacOS/Defold --port 8181 ``` ## Editor Styling Editor appearance can be changed with custom styling. Read more in the [Editor Styling manual](#manuals:editor-styling.md). ## FAQ #### Q: What are the system requirements for the editor? A: The editor will use up to 75% of the available memory of the system. On a computer with 4 GB of RAM this should be enough for smaller Defold projects. For mid-sized or large projects it is recommended to use 6 GB or more of RAM. #### Q: Are Defold beta versions auto-updating? A: Yes. The Defold beta editor checks for an update at startup, just like the Defold stable version does. #### Q: Why am I getting an error saying `java.awt.AWTError: Assistive Technology not found` when launching the editor? A: This error is related to problems with Java assistive technology such as the [NVDA screen reader](https://www.nvaccess.org/download/). You probably have an `.accessibility.properties` file in your home folder. Remove the file and try launching the editor again. (Note: If you do use any assistive technology and require that file to be present then please reach out to us at info@defold.se to discuss alternative solutions). Discussed [here on the Defold forum](https://forum.defold.com/t/editor-endless-loading-windows-10-1-2-169-solved/65481/3). #### Q: Why am I getting an error saying `sun.security.validator.ValidatorException: PKIX path building failed` when launching the editor? A: This exception occurs when the editor tries to make an https connection but the certificate chain provided by the server cannot be verified. See [this link](https://github.com/defold/defold/blob/master/editor/README_TROUBLESHOOTING_PKIX.md) for details on this error. #### Q: Why am I am getting a `java.lang.OutOfMemoryError: Java heap space` when performing certain operations? A: The Defold editor is built using Java and in some cases the default memory configuration of Java might not be sufficient. If this happens you can manually configure the editor to allocate more memory by editing the editor configuration file. The configuration file, named `config`, is located in the `Defold.app/Contents/Resources/` folder on macOS. On Windows it is located next to `Defold.exe` executable and on Linux next to the `Defold` executable. Open the `config` file and add `-Xmx6gb` to the line starting with `vmargs`. Adding `-Xmx6gb` will set the max heap size to 6 gigabytes (the default is usually 4Gb). It should look something like this: ``` vmargs = -Xmx6gb,-Dfile.encoding=UTF-8,-Djna.nosys=true,-Ddefold.launcherpath=${bootstrap.launcherpath},-Ddefold.resourcespath=${bootstrap.resourcespath},-Ddefold.version=${build.version},-Ddefold.editor.sha1=${build.editor_sha1},-Ddefold.engine.sha1=${build.engine_sha1},-Ddefold.buildtime=${build.time},-Ddefold.channel=${build.channel},-Ddefold.archive.domain=${build.archive_domain},-Djava.net.preferIPv4Stack=true,-Dsun.net.client.defaultConnectTimeout=30000,-Dsun.net.client.defaultReadTimeout=30000,-Djogl.texture.notexrect=true,-Dglass.accessible.force=false,--illegal-access=warn,--add-opens=java.base/java.lang=ALL-UNNAMED,--add-opens=java.desktop/sun.awt=ALL-UNNAMED,--add-opens=java.desktop/sun.java2d.opengl=ALL-UNNAMED,--add-opens=java.xml/com.sun.org.apache.xerces.internal.jaxp=ALL-UNNAMED ``` # The Defold scene editor {#manuals:scene-editing} The **Scene Editor** is the visual editor used to build and edit scenes such as collections, game objects, and other visual assets. By default, many visual scenes open with a **2D orthographic** view. For 3D work you can switch to a 3D-oriented layout, enable a 3D grid plane, and use a **perspective** camera. ## Opening the Scene Editor Open the Scene Editor by double-clicking a visual resource in the *Assets* pane, such as: - **Scene structure** — collections (`.collection`), game objects (`.go`) - **2D assets** — atlas (`.atlas`), tilemaps (`.tilemap`), sprites (`.sprite`), tile sources (`.tilesource`) - **3D assets** — models (`.model`, `.glb`, `.gltf`) - **UI** — GUI scenes (`.gui`) - **Effects** — particle effects (`.particlefx`) - And others ## Scene view navigation (camera controls) The Scene Editor camera can be controlled with mouse and keyboard. The available controls depend on whether you are using the standard camera navigation or **Free Camera Mode**. ### Standard navigation (all visual editors) These controls are available in visual editors: - **Pan** - `Alt`/`⌥ Option` + `Left Mouse Button` - **Zoom** - `Mouse Wheel`, or - `Ctrl`/`^ Control` + `Alt`/`⌥ Option` + `Left Mouse Button` - **Rotate/Orbit (3D) around selection** - `Ctrl`/`^ Control` + `Left Mouse Button` You may also use **Frame Selection** (`F`) to focus the camera on the current selection. ## 2D and 3D scene orientation The scene view can be used in both 2D and 3D workflows: - In **2D**, you typically work in an orthographic view with a 2D-oriented grid. - In **3D**, you typically: - Realign the view to a 3D orientation, - Use a **perspective** camera, - Choose an appropriate grid plane (often **Y** for “ground”). You can access these functions via the toolbar and the **View** menu. ## Toolbar overview In the top-right of the scene view there is a toolbar with commonly used tools and view options (left to right): - **Move tool** (`W`) - **Rotate tool** (`E`) - **Scale tool** (`R`) - **Grid Settings** (`▦`) - **Align/Realign Camera 2D/3D** (`2D`) — toggles between 2D and 3D orientation (shortcut `.`) - **Camera Perspective/Orthographic** - **Visibility Filters** (`👁`) ## Selecting and manipulating objects ### Selecting objects `Left Mouse Click` on objects in the main window to select them. The rectangle (or cuboid) surrounding the object in the editor view will highlight with cyan to indicate what item is selected. The selected object is also highlighted in the `Outline` view as in the picture above. You can also select objects by: - `Left Mouse Click` and `Drag` to select all objects inside the selection region. - `Left Mouse Click` objects in the `Outline`, and while holding `⇧ Shift` you can expand selection or while holding `Ctrl`/`⌘ Cmd` you can (un)select clicked. #### Move tool To move objects, use the *Move Tool*. You can find it in the Toolbar in the top right corner of the scene editor, or by pressing the `W` key. The gizmo changes and shows a set of manipulators - squares and arrows (selected manipulator will turn to orange color) that you can `Drag` to move: - one cyan center square handle to move the object only in the screen space, - 3 red, green and blue arrows along each axis to move the object only along the given X, Y or Z axis. - 3 red, green and blue square handles (outlined with a transparent fill) to move the object only on the given plane, e.g. X-Y (blue) and (visible if rotating the camera in 3D) X-Z (green) and Y-Z (red) planes. #### Rotate tool To rotate objects, use the *Rotate Tool* by selecting it in the Toolbar, or by pressing the `E` key. This tool consists of four circular manipulators (selected manipulator will turn to orange color) that you can `Drag` to rotate: - one cyan (outer, biggest circle) manipulator that rotates the object in the screen space - 3 smaller red, green and blue circle manipulators allowing rotation around each of the X, Y and Z axes separately. For 2D orthographic view, the two of them are perpendicular to the X- and Y-axis, so the circles only appear as two lines crossing the object. #### Scale tool To scale objects, use the *Scale Tool* by selecting it in the toolbar, or by pressing the `R` key. This tool consists of a set of square/cube manipulators (selected manipulator will turn to orange color) that you can `Drag` to scale: - one cyan cube in the center scales the object uniformly in all axes (including Z). - 3 red, blue and green cube manipulators scale the object along each of the X, Y and Z axes separately. - 3 red, green and blue square manipulators (outlined with a transparent fill) scale the object on the X-Y, X-Z or Y-Z planes separately. ### Visibility filters Click on the Visibility Eye Icon (`👁`) in the Toolbar to toggle visibility of various component types as well as bounding boxes and guide lines (`Component Guides` or shortcut `Ctrl` + `H` (Win/Linux) or `^ Ctrl` + `⌘ Cmd` + `H`(Mac)). ## Grid settings The grid can be customized to match your workflow (especially useful in 3D). Click the **Grid Settings** button (`▦`) to open the grid settings popup. Settings include: - **Grid size (X/Y/Z)** Sets the spacing between grid lines along each axis. Use smaller values for precise placement of small objects, or larger values for a broader overview. - **Active plane (X/Y/Z)** Selects which plane the grid is drawn on. In 2D workflows this is typically **Z** (the default X-Y plane). In 3D workflows, **Y** is common to represent a ground/floor plane. - **Grid color** Sets the color of the grid lines. Useful for contrast against different scene backgrounds. - **Grid opacity** Controls how transparent the grid lines are. Lower values make the grid less intrusive while still providing a reference. - A **Reset to Defaults** button Restores all grid settings to their original values. ## Camera type: Perspective vs Orthographic The Scene Editor supports both: - **Orthographic** camera (common in 2D workflows) - **Perspective** camera (common in 3D workflows) Use the camera toggle in the toolbar to switch. In 3D scenes, perspective navigation usually feels more natural. ## Free Camera Mode For fast 3D navigation, the Scene Editor provides **Free Camera Mode**, a first-person / “FPS-style” camera. ### Activating Free Camera Mode - Hold `Right Mouse Button` — Free Camera Mode is active as long as the button is held - `Shift` + ``` (backtick) — toggles Free Camera Mode on, keeping it active after release On some keyboard layouts (e.g. Swedish) the backtick key is a dead key and may not trigger the shortcut as expected. You can rebind this shortcut in `File ▸ Preferences ▸ Keys` and enter a shortcut for `Scene -> Free Camera -> Activate` When Free Camera Mode is active the Scene View is highlighted with a line around the edges. ### Exiting Free Camera Mode - Release `Right Mouse Button` (when activated by hold), or - `Left Mouse Button`, `Right Mouse Button` (press and release), or press `Esc` when Free Camera Mode was activated as a toggle. ### Looking around (mouse look) While Free Camera Mode is active, these keys control camera movement (instead of editor tools): - Move the mouse to control **yaw** (left/right) and **pitch** (up/down) - Pitch is clamped to avoid flipping the camera You can also optionally invert the Y axis (see **Free camera settings** below). ### Moving While Free Camera Mode is active: - `W` — forward - `S` — backward - `A` — left - `D` — right - `E` — up - `Q` — down All movement keys can be rebound in `File ▸ Preferences ▸ Keys`. Then search for `Scene -> Free Camera` Speed modifiers: - Hold `Shift` — move faster - Hold `Alt`/`⌥ Option` — move slower / more precisely ### Walking mode (optional) Free Camera Mode supports **Walking Mode**. When enabled: - Up/down movement is constrained to behave more like grounded first-person walking on a ground plane. - This is useful when exploring a level and you want consistent “grounded” movement. ## Camera settings popup The perspective camera button in the toolbar has a settings popup for camera-related preferences. The popup contains: - **Move Speed** Adjusts free camera movement speed. - **Look Sensitivity** Adjusts how quickly the camera rotates in response to mouse movement. - **Invert Y** Inverts vertical mouse look. - **Walking Mode** Constrains movement for ground-like navigation. - **Reset to Defaults** Restores default camera settings. # Writing code {#manuals:writing-code} While Defold allows you to create a lot of your game content using visual tools such as the tilemap and particle effect editors you still create your game logic using a code editor. Game logic is written using the [Lua programming language](https://www.lua.org/) while extensions to the engine itself are written using the native language(s) for the target platform. ## Writing Lua code Defold uses Lua 5.1 and LuaJIT (depending on target platform) and you need to follow the language specification for those specific versions of Lua when writing your game logic. For more details on how to work with Lua in Defold see our [Lua in Defold manual](#manuals:lua). ## Using other languages that transpile to Lua Defold supports the use of transpilers that emit Lua code. With transpiler extension installed, you can use alternative languages — such as [Teal](https://github.com/defold/extension-teal) — to write statically-checked Lua. It is a preview feature that has limitations: current transpiler support does not expose the information about modules and functions defined in the Defold Lua runtime. It means that using Defold APIs like `go.animate` will require you to write external definitions yourself. ## Writing native code Defold allows you to extend the game engine with native code to access platform specific functionality not provided by the engine itself. You can also use native code when the performance of Lua isn't enough (resource intensive calculations, image processing etc). Refer to our [manuals on Native Extensions](#manuals:extensions) to learn more. ## Using the built-in code editor Defold has a built-in code editor that allows you to open and edit Lua files (.lua), Defold script files (.script, .gui_script and .render_script) as well as any other file with a file extension not natively handled by the editor. Additionally the editor provides syntax highlighting for Lua and script files. ### Code completion The built-in code editor will show code completion of functions while writing code: Pressing `CTRL` + `Space` will show additional information about functions, arguments and return values: ### Linting configuration The built-in code editor performs code linting using [Luacheck](https://luacheck.readthedocs.io/en/stable/index.html) and [Lua language server](https://luals.github.io/wiki/diagnostics/). To configure the Luacheck, create a `.luacheckrc` file in the project root. You can read the [Luacheck configuration page](https://luacheck.readthedocs.io/en/stable/config.html) for the list of the available options. Defold uses the following defaults for the Luacheck configuration: ```lua unused_args = false -- don't warn on unused arguments (common for .script files) max_line_length = false -- don't warn on long lines ignore = { "611", -- line contains only whitespace "612", -- line contains trailing whitespace "614" -- trailing whitespace in a comment }, ``` ## Using an external code editor The code editor in Defold provides the basic functionality you need to write code, but for more advanced use cases or for power users with a favorite code editor it is possible to let Defold open files using an external editor. In the [Preferences window under the Code tab](#manuals:editor-preferences) it is possible to define an external editor that should be used when editing code. ### Visual Studio Code - Defold Kit Defold Kit is a Visual Studio Code plugin with the following features: * Installing recommended extensions * Lua highlighting, autocompletion and linting * Applying relevant settings to the workspace * Lua annotations for Defold API * Lua annotations for dependencies * Building and launching * Debugging with breakpoints * Bundling for all the platforms * Deploying to connected mobile devices Learn more and install Defold Kit from the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=astronachos.defold). ## Documentation software Community created API reference packages are available for [Dash and Zeal](https://forum.defold.com/t/defold-docset-for-dash/2417). # Editor templates {#manuals:editor-templates} You can add your own custom project templates to the New Project window: In order to add one or more new tabs with custom project templates you need to add a `welcome.edn` file in the `.defold` folder in your user home directory: * Create a folder named `.defold` in your user home directory. * On Windows `C:\Users\**Your Username**\.defold` * On macOS `/Users/**Your Username**/.defold` * On Linux `~/.defold` * Create a `welcome.edn` file in the `.defold` folder The `welcome.edn` file uses the Extensible Data Notation format. Example: ``` {:new-project {:categories [ {:label "My Templates" :templates [ {:name "My project" :description "My template with everything set up the way I want it." :image "empty.svg" :zip-url "https://github.com/britzl/template-project/archive/master.zip" :skip-root? true}, {:name "My other project" :description "My other template with everything set up the way I want it." :image "empty.svg" :zip-url "https://github.com/britzl/template-other-project/archive/master.zip" :skip-root? true}] }] } } ``` This will create the list of templates seen in the screenshot above. You can only use the template images [bundled with the editor](https://github.com/defold/defold/tree/dev/editor/resources/welcome/images). # Editor scripts {#manuals:editor-scripts} You can create custom menu items and editor lifecycle hooks using Lua files with special extension: `.editor_script`. Using this system, you can tweak editor to enhance your development workflow. ## Editor script runtime Editor scripts run inside an editor, in a Lua VM emulated by Java VM. All scripts share the same single environment, which means they can interact with each other. You can require Lua modules, just as with `.script` files, but Lua version that is running inside the editor is different, so make sure your shared code is compatible. Editor uses Lua version 5.2.x, more specifically [luaj](https://github.com/luaj/luaj) runtime, which is currently the only viable solution to run Lua on JVM. Besides that, there are some restrictions: - there is no `debug` package; - there is no `os.execute`, though we provide a similar `editor.execute()`; - there is no `os.tmpname` and `io.tmpfile` — currently editor scripts can access files only inside the project directory; - there is currently no `os.rename`, although we want to add it; - there is no `os.exit` and `os.setlocale`. - it's not allowed to use some long-running functions in contexts where the editor needs an immediate response from the script, see [Execution Modes](#execution-modes) for more details. All editor extensions defined in editor scripts are loaded when you open a project. When you fetch libraries, extensions are reloaded, since there might be new editor scripts in a libraries you depend on. During this reload, no changes in your own editor scripts are picked up, since you might be in the middle of changing them. To reload them as well, you should run **Project → Reload Editor Scripts** command. ## Anatomy of `.editor_script` Every editor script should return a module, like that: ```lua local M = {} function M.get_commands() -- TODO - define editor commands end function M.get_language_servers() -- TODO - define language servers end function M.get_prefs_schema() -- TODO - define preferences end return M ``` Editor then collects all editor scripts defined in project and libraries, loads them into single Lua VM and calls into them when needed (more on that in [commands](#commands) and [lifecycle hooks](#lifecycle-hooks) sections). ## Editor API You can interact with the editor using `editor` package that defines this API: - `editor.platform` — a string, either `"x86_64-win32"` for Windows, `"x86_64-macos"` for macOS or `"x86_64-linux"` for Linux. - `editor.version` — a string, version name of Defold, e.g. `"1.4.8"` - `editor.engine_sha1` — a string, SHA1 of Defold engine - `editor.editor_sha1` — a string, SHA1 of Defold editor - `editor.get(node_id, property)` — get a value of some node inside the editor. Nodes in the editor are various entities, such as script or collection files, game objects inside collections, json files loaded as resources, etc. `node_id` is a userdata that is passed to the editor script by the editor. Alternatively, you can pass resource path instead of node id, for example `"/main/game.script"`. `property` is a string. Currently these properties are supported: - `"path"` — file path from the project folder for *resources* — entities that exist as files or directories. Example of returned value: `"/main/game.script"` - `"children"` — list of children resource paths for directory resources - `"text"` — text content of a resource editable as text (such as script files or json). Example of returned value: `"function init(self)\nend"`. Please note that this is not the same as reading file with `io.open()`, because you can edit a file without saving it, and these edits are available only when accessing `"text"` property. - for atlases: `images` (list of editor nodes for images in the atlas) and `animations` (list of animation nodes) - for atlas animations: `images` (same as `images` in atlas) - for tilemaps: `layers` (list of editor nodes for layers in the tilemap) - for tilemap layers: `tiles` (an unbounded 2d grid of tiles), see `tilemap.tiles.*` for more info - for particlefx: `emitters` (list of emitter editor nodes) and `modifiers` (list of modifier editor nodes) - for particlefx emitters: `modifiers` (list of modifier editor nodes) - for collision objects: `shapes` (list of collision shape editor nodes) - for GUI files: `layers` (list of layer editor nodes) - some properties that are shown in the Properties view when you have selected something in the Outline view. These types of outline properties supported: - `strings` - `booleans` - `numbers` - `vec2`/`vec3`/`vec4` - `resources` - `curves` Please note that some of these properties might be read-only, and some might be unavailable in different contexts, so you should use `editor.can_get` before reading them and `editor.can_set` before making editor set them. Hover over property name in Properties view to see a tooltip with information about how this property is named in editor scripts. You can set resource properties to `nil` by supplying `""` value. - `editor.can_get(node_id, property)` — check if you can get this property so `editor.get()` won't throw an error. - `editor.can_set(node_id, property)` — check if `editor.tx.set()` transaction step with this property won't throw an error. - `editor.create_directory(resource_path)` — create a directory if it does not exist, and all non-existent parent directories. - `editor.create_resources(resources)` — create 1 or more resources, either from templates or with custom content - `editor.delete_directory(resource_path)` — delete a directory if it exists, and all existent child directories and files. - `editor.execute(cmd, [...args], [options])` — run a shell command, optionally capturing its output. - `editor.save()` — persist all unsaved changed to disk. - `editor.transact(txs)` — modify the editor in-memory state using 1 or more transaction steps created with `editor.tx.*` functions. - `editor.ui.*` — various UI-related functions, see [UI manual](#manuals:editor-scripts-ui). - `editor.prefs.*` — functions for interacting with editor preferences, see [preferences](#preferences). You can find the full editor API reference [here](https://defold.com/ref/alpha/editor/). ## Commands If editor script module defines function `get_commands`, it will be called on extension reload, and returned commands will be available for use inside the editor in menu bar or in context menus in Assets and Outline panes. Example: ```lua local M = {} function M.get_commands() return { { label = "Remove Comments", locations = {"Edit", "Assets"}, query = { selection = {type = "resource", cardinality = "one"} }, active = function(opts) local path = editor.get(opts.selection, "path") return ends_with(path, ".lua") or ends_with(path, ".script") end, run = function(opts) local text = editor.get(opts.selection, "text") editor.transact({ editor.tx.set(opts.selection, "text", strip_comments(text)) }) end }, { label = "Minify JSON", locations = {"Assets"}, query = { selection = {type = "resource", cardinality = "one"} }, active = function(opts) return ends_with(editor.get(opts.selection, "path"), ".json") end, run = function(opts) local path = editor.get(opts.selection, "path") editor.execute("./scripts/minify-json.sh", path:sub(2)) end } } end return M ``` Editor expects `get_commands()` to return an array of tables, each describing a separate command. Command description consists of: - `label` (required) — text on a menu item that will be displayed to the user - `locations` (required) — an array of either `"Edit"`, `"View"`, `"Project"`, `"Debug"`, `"Assets"`, `"Bundle"`, `"Scene"` or `"Outline"`, describes a place where this command should be available. `"Edit"`, `"View"`, `"Project"` and `"Debug"` mean menu bar at the top, `"Assets"` means context menu in Assets pane, `"Outline"` means context menu in Outline pane, and `"Bundle"` means **Project → Bundle** submenu. - `query` — a way for command to ask editor for relevant information and define what data it operates on. For every key in `query` table there will be corresponding key in `opts` table that `active` and `run` callbacks receive as argument. Supported keys: - `selection` means this command is valid when there is something selected, and it operates on this selection. - `type` is a type of selected nodes command is interested in, currently these types are allowed: - `"resource"` — in Assets and Outline, resource is selected item that has a corresponding file. In menu bar (Edit or View), resource is a currently open file; - `"outline"` — something that can be shown in the Outline. In Outline it's a selected item, in menu bar it's a currently open file; - `"scene"` — something that can be rendered to the Scene. - `cardinality` defines how many selected items there should be. If `"one"`, selection passed to command callback will be a single node id. If `"many"`, selection passed to command callback will be an array of one or more node ids. - `argument` — command argument. Currently, only commands in `"Bundle"` location receive an argument, which is `true` when the bundle command is selected explicitly and `false` on rebundle. - `id` - command identifier string, used e.g. for persisting the last used bundle command in `prefs` - `active` - a callback that is executed to check that command is active, expected to return boolean. If `locations` include `"Assets"`, `"Scene"` or `"Outline"`, `active` will be called when showing context menu. If locations include `"Edit"` or `"View"`, active will be called on every user interaction, such as typing on keyboard or clicking with mouse, so be sure that `active` is relatively fast. - `run` - a callback that is executed when user selects the menu item. ### Use commands to change the in-memory editor state Inside the `run` handler, you can query and change the in-memory editor state. Querying is done using `editor.get()` function, where you can ask the editor about the current state of files and selection (if using `query = {selection = ...}`). You can get the `"text"` property of script files, and also some properties shown in the Properties view — hover over property name to see a tooltip with information about how this property is named in editor scripts. Changing the editor state is done using `editor.transact()`, where you bundle 1 or more modifications in a single undoable step. For example, if you want to be able to reset transform of a game object, you could write a command like that: ```lua { label = "Reset transform", locations = {"Outline"}, query = {selection = {type = "outline", cardinality = "one"}}, active = function(opts) local node = opts.selection return editor.can_set(node, "position") and editor.can_set(node, "rotation") and editor.can_set(node, "scale") end, run = function(opts) local node = opts.selection editor.transact({ editor.tx.set(node, "position", {0, 0, 0}), editor.tx.set(node, "rotation", {0, 0, 0}), editor.tx.set(node, "scale", {1, 1, 1}) }) end } ``` #### Editing atlases In addition to reading and writing properties of an atlas, you can read and modify atlas images and animations. Atlas defines `images` and `animations` node list properties, and animations define `images` node list property: you can use `editor.tx.add`, `editor.tx.remove` and `editor.tx.clear` transaction steps with these properties. For example, to add an image to an atlas, execute the following code in the command's `run` handler: ```lua editor.transact({ editor.tx.add("/main.atlas", "images", {image="/assets/hero.png"}) }) ``` To find a set of all images in an atlas, execute the following code: ```lua local all_images = {} ---@type table -- first, collect all "bare" images local image_nodes = editor.get("/main.atlas", "images") for i = 1, #image_nodes do all_images[editor.get(image_nodes[i], "image")] = true end -- second, collect all images used in animations local animation_nodes = editor.get("/main.atlas", "animations") for i = 1, #animation_nodes do local animation_image_nodes = editor.get(animation_nodes[i], "images") for j = 1, #animation_image_nodes do all_images[editor.get(animation_image_nodes[j], "image")] = true end end pprint(all_images) -- { -- ["/assets/hero.png"] = true, -- ["/assets/enemy.png"] = true, -- }} ``` To replace all animations in an atlas: ```lua editor.transact({ editor.tx.clear("/main.atlas", "animations"), editor.tx.add("/main.atlas", "animations", { id = "hero_run", images = { {image = "/assets/hero_run_1.png"}, {image = "/assets/hero_run_2.png"}, {image = "/assets/hero_run_3.png"}, {image = "/assets/hero_run_4.png"} } }) }) ``` #### Editing tilesources In addition to outline properties, tilesources define the following properties: - `animations` - a list of animation nodes of the tilesource - `collision_groups` - a list of collision group nodes of the tilesource - `tile_collision_groups` - a table of collision group assignments for tiles in the tilesource For example, here is how you can setup a tilesource: ```lua local tilesource = "/game/world.tilesource" editor.transact({ editor.tx.add(tilesource, "animations", {id = "idle", start_tile = 1, end_tile = 1}), editor.tx.add(tilesource, "animations", {id = "walk", start_tile = 2, end_tile = 6, fps = 10}), editor.tx.add(tilesource, "collision_groups", {id = "player"}), editor.tx.add(tilesource, "collision_groups", {id = "obstacle"}), editor.tx.set(tilesource, "tile_collision_groups", { [1] = "player", [7] = "obstacle", [8] = "obstacle" }) }) ``` #### Editing tilemaps Tilemaps define `layers` property, a node list of tilemap layers. Each layer also defines a `tiles` property that holds an unbounded 2d grid of tiles on this layer. This is different from the engine: tiles have no bounds and may be added anywhere, including negative coordinates. To edit tiles, the editor script API defines a `tilemap.tiles` module with the following functions: - `tilemap.tiles.new()` to create a fresh data structure that holds an unbounded 2d tile grid (in the editor, contrary to the engine, the tilemap is unbounded, and coordinates may be negative) - `tilemap.tiles.get_tile(tiles, x, y)` to get a tile index at a specific coordinate - `tilemap.tiles.get_info(tiles, x, y)` to get full tile information at a specific coordinate (the data shape is the same as in the engine's `tilemap.get_tile_info` function) - `tilemap.tiles.iterator(tiles)` to create an iterator over all tiles in the tilemap - `tilemap.tiles.clear(tiles)` to remove all tiles from the tilemap - `tilemap.tiles.set(tiles, x, y, tile_or_info)` to set a tile at a specific coordinate - `tilemap.tiles.remove(tiles, x, y)` to remove a tile at a specific coordinate For example, here is how you can print the contents of the whole tilemap: ```lua local layers = editor.get("/level.tilemap", "layers") for i = 1, #layers do local layer = layers[i] local id = editor.get(layer, "id") local tiles = editor.get(layer, "tiles") print("layer " .. id .. ": {") for x, y, tile in tilemap.tiles.iterator(tiles) do print(" [" .. x .. ", " .. y .. "] = " .. tile) end print("}") end ``` Here is an example that shows how to add a layer with tiles to a tilemap: ```lua local tiles = tilemap.tiles.new() tilemap.tiles.set(tiles, 1, 1, 2) editor.transact({ editor.tx.add("/level.tilemap", "layers", { id = "new_layer", tiles = tiles }) }) ``` #### Editing particlefx You can edit particlefx using `modifiers` and `emitters` properties. For example, adding a circle emitter with acceleration modifier is done like this: ```lua editor.transact({ editor.tx.add("/fire.particlefx", "emitters", { type = "emitter-type-circle", modifiers = { {type = "modifier-type-acceleration"} } }) }) ``` Many particlefx properties are curves or curve spreads (i.e. curve + some randomizer value). Curves are represented as a table with a non-empty list of `points`, where each point is a table with the following properties: - `x` - the x coordinate of the point, should start at 0 and end at 1 - `y` - the value of the point - `tx` (0 to 1) and `ty` (-1 to 1) - tangents of the point. E.g., for an 80-degree angle, `tx` should be `math.cos(math.rad(80))` and `ty` should be `math.sin(math.rad(80))`. Curve spreads additionally have a `spread` number property. For example, setting a particle lifetime alpha curve for an already existing emitter might look like this: ```lua local emitter = editor.get("/fire.particlefx", "emitters")[1] editor.transact({ editor.tx.set(emitter, "particle_key_alpha", { points = { {x = 0, y = 0, tx = 0.1, ty = 1}, -- start at 0, go up quickly {x = 0.2, y = 1, tx = 1, ty = 0}, -- reach 1 at 20% of a lifetime {x = 1, y = 0, tx = 1, ty = 0} -- slowly go down to 0 }}) }) ``` Of course, it's also possible to use the `particle_key_alpha` key in a table when creating an emitter. Additionally, you can use a single number instead to represent a "static" curve. #### Editing collision objects In addition to default outline properties, collision objects define `shapes` node list property. Adding new collision shapes is done like this: ```lua editor.transact({ editor.tx.add("/hero.collisionobject", "shapes", { type = "shape-type-box" -- or "shape-type-sphere", "shape-type-capsule" }) }) ``` Shape's `type` property is required during creation and cannot be changed after the shape is added. There are 3 shape types: - `shape-type-box` - box shape with `dimensions` property - `shape-type-sphere` - sphere shape with `diameter` property - `shape-type-capsule` - capsule shape with `diameter` and `height` properties #### Editing GUI files In addition to outline properties, GUI nodes defines the following properties: - `layers` — list of layer editor nodes (reorderable) - `materials` — list of material editor nodes It's possible to edit GUI layers using editor `layers` property, e.g.: ```lua editor.transact({ editor.tx.add("/main.gui", "layers", {name = "foreground"}), editor.tx.add("/main.gui", "layers", {name = "background"}) }) ``` Additionally, it's possible to reorder layers: ```lua local fg, bg = table.unpack(editor.get("/main.gui", "layers")) editor.transact({ editor.tx.reorder("/main.gui", "layers", {bg, fg}) }) ``` Similarly, fonts, materials, textures, and particlefxs are edited using `fonts`, `materials`, `textures`, and `particlefxs` properties: ```lua editor.transact({ editor.tx.add("/main.gui", "fonts", {font = "/main.font"}), editor.tx.add("/main.gui", "materials", {name = "shine", material = "/shine.material"}), editor.tx.add("/main.gui", "particlefxs", {particlefx = "/confetti.material"}), editor.tx.add("/main.gui", "textures", {texture = "/ui.atlas"}) }) ``` These properties don't support reordering. Finally, you can edit GUI nodes using `nodes` list property, e.g.: ```lua editor.transact({ editor.tx.add("/main.gui", "nodes", { type = "gui-node-type-box", position = {20, 20, 20} }), editor.tx.add("/main.gui", "nodes", { type = "gui-node-type-template", template = "/button.gui" }), }) ``` Built-in node types are: - `gui-node-type-box` - `gui-node-type-particlefx` - `gui-node-type-pie` - `gui-node-type-template` - `gui-node-type-text` If you are using spine extension, you can also use `gui-node-type-spine` node type. If the GUI file defines layouts, you can get and set the values from layouts using `layout:property` syntax, e.g.: ```lua local node = editor.get("/main.gui", "nodes")[1] -- GET: local position = editor.get(node, "position") pprint(position) -- {20, 20, 20} local landscape_position = editor.get(node, "Landscape:position") pprint(landscape_position) -- {20, 20, 20} -- SET: editor.transact({ editor.tx.set(node, "Landscape:position", {30, 30, 30}) }) pprint(editor.get(node, "Landscape:position")) -- {30, 30, 30} ``` Layout properties that were set can be reset to their default values using `editor.tx.reset`: ```lua print(editor.can_reset(node, "Landscape:position")) -- true editor.transact({ editor.tx.reset(node, "Landscape:position") }) ``` Template node trees can be read, but not edited — you can only set node properties of the template node tree: ```lua local template = editor.get("/main.gui", "nodes")[2] print(editor.can_add(template, "nodes")) -- false local node_in_template = editor.get(template, "nodes")[1] editor.transact({ editor.tx.set(node_in_template, "text", "Button text") }) print(editor.can_reset(node_in_template, "text")) -- true (overrides a value in the template) ``` #### Editing game objects It's possible to edit components of a game object file using editor scripts. The components come in 2 flavors: referenced and embedded. Referenced components use type `component-reference` and act as references to other resources, only allowing overrides of go properties defined in scripts. Embedded components use types like `sprite`, `label`, etc., and allow editing of all properties defined in the component type, as well as adding sub-components like shapes of collision objects. For example, you can use the following code to set up a game object: ```lua editor.transact({ editor.tx.add("/npc.go", "components", { type = "sprite", id = "view" }), editor.tx.add("/npc.go", "components", { type = "collisionobject", id = "collision", shapes = { { type = "shape-type-box", dimensions = {32, 32, 32} } } }), editor.tx.add("/npc.go", "components", { type = "component-reference", path = "/npc.script" id = "controller", __hp = 100 -- set a go property defined in the script }) }) ``` #### Editing collections It's possible to edit collections using editor scripts. You can add game objects (embedded or referenced) and collections (referenced). For example: ```lua local coll = "/char.collection" editor.transact({ editor.tx.add(coll, "children", { -- embbedded game object type = "go", id = "root", children = { { -- referenced game object type = "go-reference", path = "/char-view.go" id = "view" }, { -- referenced collection type = "collection-reference", path = "/body-attachments.collection" id = "attachments" } }, -- embedded gos can also have components components = { { type = "collisionobject", id = "collision", shapes = { {type = "shape-type-box", dimensions = {2.5, 2.5, 2.5}} } }, { type = "component-reference", id = "controller", path = "/char.script", __hp = 100 -- set a go property defined in the script } } }) }) ``` Like in the editor, referenced collections can only be added to the root of the edited collection, and game objects can only be added to embedded or referenced game objects, but not to referenced collections or game objects within these referenced collections. ### Use shell commands Inside the `run` handler, you can write to files (using `io` module) and execute shell commands (using `editor.execute()` command). When executing shell commands, it's possible to capture the output of a shell command as a string and then use it in code. For example, if you want to make a command for formatting JSON that shells out to globally installed [`jq`](https://jqlang.github.io/jq/), you can write the following command: ```lua { label = "Format JSON", locations = {"Assets"}, query = {selection = {type = "resource", cardinality = "one"}}, action = function(opts) local path = editor.get(opts.selection, "path") return path:match(".json$") ~= nil end, run = function(opts) local text = editor.get(opts.selection, "text") local new_text = editor.execute("jq", "-n", "--argjson", "data", text, "$data", { reload_resources = false, -- don't reload resources since jq does not touch disk out = "capture" -- return text output instead of nothing }) editor.transact({ editor.tx.set(opts.selection, "text", new_text) }) end } ``` Since this command invokes shell program in a read-only way (and notifies the editor about it using `reload_resources = false`), you get the benefit of making this action undoable. If you want to distribute your editor script as a library, you might want to bundle the binary program for editor platforms within the dependency. See [Editor scripts in libraries](#editor-scripts-in-libraries) for more details on how to do it. ## Lifecycle hooks There is a specially treated editor script file: `hooks.editor_script`, located in a root of your project, in the same directory as *game.project*. This and only this editor script will receive lifecycle events from the editor. Example of such file: ```lua local M = {} function M.on_build_started(opts) local file = io.open("assets/build.json", "w") file:write('{"build_time": "' .. os.date() .. '"}') file:close() end return M ``` We decided to limit lifecycle hooks to single editor script file because order in which build hooks happen is more important than how easy it is to add another build step. Commands are independent from each other, so it does not really matter in what order they are shown in the menu, in the end user executes a particular command they selected. If it was possible to specify build hooks in different editor scripts, it would create a problem: in which order do hooks execute? You probably want to create a checksums of content after you compress it... And having a single file that establishes order of build steps by calling each step function explicitly is a way to solve this problem. Existing lifecycle hooks that `/hooks.editor_script` may specify: - `on_build_started(opts)` — executed when game is Built to run locally or on some remote target using either the Project Build or Debug Start options. Your changes will appear in the built game. Raising an error from this hook will abort a build. `opts` is a table that contains following keys: - `platform` — a string in `%arch%-%os%` format describing what platform it's built for, currently always the same value as in `editor.platform`. - `on_build_finished(opts)` — executed when build is finished, be it successful or failed. `opts` is a table with following keys: - `platform` — same as in `on_build_started` - `success` — whether build is successful, either `true` or `false` - `on_bundle_started(opts)` — executed when you create a bundle or Build HTML5 version of a game. As with `on_build_started`, changes triggered by this hook will appear in a bundle, and errors will abort a bundle. `opts` will have these keys: - `output_directory` — a file path pointing to a directory with bundle output, for example `"/path/to/project/build/default/__htmlLaunchDir"` - `platform` — platform the game is bundled for. See a list of possible platform values in [Bob manual](#manuals:bob). - `variant` — bundle variant, either `"debug"`, `"release"` or `"headless"` - `on_bundle_finished(opts)` — executed when bundle is finished, be it successful or not. `opts` is a table with the same data as `opts` in `on_bundle_started`, plus `success` key indicating whether build is successful. - `on_target_launched(opts)` — executed when user launched a game and it successfully started. `opts` contains an `url` key pointing to a launched engine service, for example, `"http://127.0.0.1:35405"` - `on_target_terminated(opts)` — executed when launched game is closed, has same opts as `on_target_launched` Please note that lifecycle hooks currently are an editor-only feature, and they are not executed by Bob when bundling from command line. ## Language servers The editor supports a subset [Language Server Protocol](https://microsoft.github.io/language-server-protocol/). While we aim to expand the editor's support for LSP features in the future, currently it can only show diagnostics (i.e. lints) in the edited files and provide completions. To define the language server, you need to edit your editor script's `get_language_servers` function like so: ```lua function M.get_language_servers() local command = 'build/plugins/my-ext/plugins/bin/' .. editor.platform .. '/lua-lsp' if editor.platform == 'x86_64-win32' then command = command .. '.exe' end return { { languages = {'lua'}, watched_files = { { pattern = '**/.luacheckrc' } }, command = {command, '--stdio'} } } end ``` The editor will start the language server using the specified `command`, using the server process's standard input and output for communication. Language server definition table may specify: - `languages` (required) — a list of languages the server is interested in, as defined [here](https://code.visualstudio.com/docs/languages/identifiers#known-language-identifiers) (file extensions also work); - `command` (required) - an array of command and its arguments - `watched_files` - an array of tables with `pattern` keys (a glob) that will trigger the server's [watched files changed](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_didChangeWatchedFiles) notification. ## HTTP server Every running instance of the editor has an HTTP server running. The server can be extended using editor scripts. To extend the editor HTTP server, you need to add `get_http_server_routes` editor script function — it should return the additional routes: ```lua print("My route: " .. http.server.url .. "/my-extension") function M.get_http_server_routes() return { http.server.route("/my-extension", "GET", function(request) return http.server.response(200, "Hello world!") end) } end ``` After reloading the editor scripts, you'll see the following output in the console: `My route: http://0.0.0.0:12345/my-extension`. If you open this link in the browser, you'll see your `"Hello world!"` message. The input `request` argument is a simple Lua table with information about the request. It contains keys such as `path` (URL path segment that starts with `/`), request `method` (e.g. `"GET"`), `headers` (a table with lower-case header names), and optionally `query` (the query string) and `body` (if the route defines how to interpret the body). For example, if you want to make a route that accepts JSON body, you define it with a `"json"` converter parameter: ```lua http.server.route("/my-extension/echo-request", "POST", "json", function(request) return http.server.json_response(request) end) ``` You can test this endpoint in the command line using `curl` and `jq`: ```sh curl 'http://0.0.0.0:12345/my-extension/echo-request?q=1' -X POST --data '{"input": "json"}' | jq { "path": "/my-extension/echo-request", "method": "POST", "query": "q=1", "headers": { "host": "0.0.0.0:12345", "content-type": "application/x-www-form-urlencoded", "accept": "*/*", "user-agent": "curl/8.7.1", "content-length": "17" }, "body": { "input": "json" } } ``` The route path supports patterns that can be extracted from the request path and provided to the handler function as a part of the request, e.g.: ```lua http.server.route("/my-extension/setting/{category}.{key}", function(request) return http.server.response(200, tostring(editor.get("/game.project", request.category .. "." .. request.key))) end) ``` Now, if you open e.g. `http://0.0.0.0:12345/my-extension/setting/project.title`, you'll see the title of your game taken from the `/game.project` file. In addition to a single segment paths pattern, you can also match the rest of the URL path using `{*name}` syntax. For example, here is a simple file server endpoint that serves files from the project root: ```lua http.server.route("/my-extension/files/{*file}", function(request) local attrs = editor.external_file_attributes(request.file) if attrs.is_file then return http.server.external_file_response(request.file) else return 404 end end) ``` Now, opening e.g. `http://0.0.0.0:12345/my-extension/files/main/main.collection` in the browser will display the contents of the `main/main.collection` file. ## Editor scripts in libraries You can publish libraries for other people to use that contain commands, and they will be automatically picked up by the editor. Hooks, on the other hand, can't be picked up automatically, since they have to be defined in a file that is in a root folder of a project, but libraries expose only subfolders. This is intended to give more control over build process: you still can create lifecycle hooks as simple functions in `.lua` files, so users of your library can require and use them in their `/hooks.editor_script`. Also note that although dependencies are shown in Assets view, they do not exist as files (they are entries in a zip archive). It's possible to make the editor extract some files from the dependencies into `build/plugins/` folder. To do it, you need to create `ext.manifest` file in your library folder, and then create `plugins/bin/${platform}` folder in the same folder where the `ext.manifest` file is located. Files in that folder will be automatically extracted to `/build/plugins/${extension-path}/plugins/bin/${platform}` folder, so your editor scripts can reference them. ## Preferences Editor scripts can define and use preferences — persistent, uncommitted pieces of data stored on the user's computer. These preferences have three key characteristics: - typed: every preference has a schema definition that includes the data type and other metadata like default value - scoped: preferences are scoped either per project or per user - nested: every preference key is a dot-separated string, where the first path segment identifies an editor script, and the rest All preferences must be registered by defining their schema: ```lua function M.get_prefs_schema() return { ["my_json_formatter.jq_path"] = editor.prefs.schema.string(), ["my_json_formatter.indent.size"] = editor.prefs.schema.integer({default = 2, scope = editor.prefs.SCOPE.PROJECT}), ["my_json_formatter.indent.type"] = editor.prefs.schema.enum({values = {"spaces", "tabs"}, scope = editor.prefs.SCOPE.PROJECT}), } end ``` After such editor script is reloaded, the editor registers this schema. Then the editor script can get and set the preferences, e.g.: ```lua -- Get a specific preference editor.prefs.get("my_json_formatter.indent.type") -- Returns: "spaces" -- Get an entire preference group editor.prefs.get("my_json_formatter") -- Returns: -- { -- jq_path = "", -- indent = { -- size = 2, -- type = "spaces" -- } -- } -- Set multiple nested preferences at once editor.prefs.set("my_json_formatter.indent", { type = "tabs", size = 1 }) ``` ## Execution modes The editor script runtime uses 2 execution modes that are mostly transparent to editor scripts: **immediate** and **long-running**. **Immediate** mode is used when the editor needs to receive a response from the script as fast as possible. For instance, menu commands' `active` callbacks are executed in immediate mode, because these checks are performed on the editors UI thread in response to user interacting with the editor, and should update the UI within the same frame. **Long-running** mode is used when the editor doesn't need an instantaneous response from the script. For example, menu commands' `run` callbacks are executed in a **long-running** mode, allowing the script to take more time to complete its work. Some of the functions that the editor scripts can use may take a lot of time to run. For example, `editor.execute("git", "status", {reload_resources=false, out="capture"})` can take up to a second on sufficiently large projects. To maintain editor responsiveness and performance, functions that may be time-consuming are not allowed in contexts where the editor needs an immediate response. Attempting to use such a function in an immediate context will result in an error: `Cannot use long-running editor function in immediate context`. To resolve this error, avoid using such functions in immediate contexts. The following functions are considered long-running and cannot be used in immediate mode: - `editor.create_directory()`, `editor.create_resources()`, `editor.delete_directory()`, `editor.save()`, `os.remove()` and `file:write()`: these functions modify the files on disc, causing the editor to synchronize its in-memory resource tree with the disc state, which can take seconds in large projects. - `editor.execute()`: execution of shell commands can take an unpredictable amount of time. - `editor.transact()`: large transactions on widely-referenced nodes may take hundreds of milliseconds, which is too slow for UI responsiveness. The following code execution contexts use immediate mode: - Menu command's `active` callbacks: the editor needs a response from the script within the same UI frame. - Top-level of editor scripts: we don't expect the act of reloading editor scripts to have any side effects. ## Actions Previously, the editor interacted with the Lua VM in a blocking way, so there was a hard requirement for editor scripts to not block, since some interactions have to be done from the editor UI thread. For that reason, there was e.g. no `editor.execute()` and `editor.transact()`. Executing scripts and changing the editor state was instead triggered by returning an array of "actions" from hooks and command `run` handlers. Now the editor interacts with the Lua VM in a non-blocking way, so there is no need for these actions any more: using functions like `editor.execute()` is more convenient, concise, and powerful. The actions are now **DEPRECATED**, though we have no plans to remove them. Editor scripts may return an array of actions from a command's `run` function or from `/hooks.editor_script`'s hook functions. These actions will then be performed by the editor. Action is a table describing what editor should do. Every action has an `action` key. Actions come in 2 flavors: undoable and non-undoable. ### Undoable actions Prefer using `editor.transact()`. Undoable action can be undone after it is executed. If a command returns multiple undoable actions, they are performed together, and get undone together. You should use undoable actions if you can. Their downside is that they are more limited. Existing undoable actions: - `"set"` — set a property of a node in the editor to some value. Example: ```lua { action = "set", node_id = opts.selection, property = "text", value = "current time is " .. os.date() } ``` `"set"` action requires these keys: - `node_id` — node id userdata. Alternatively, you can use resource path here instead of node id you received from the editor, for example `"/main/game.script"`; - `property` — a property of a node to set, e.g. `"text"`; - `value` — new value for a property. For `"text"` property it should be a string. ### Non-undoable actions Prefer using `editor.execute()`. Non-undoable action clears undo history, so if you want to undo such action, you will have to use other means, such as version control. Existing non-undoable actions: - `"shell"` — execute a shell script. Example: ```lua { action = "shell", command = { "./scripts/minify-json.sh", editor.get(opts.selection, "path"):sub(2) -- trim leading "/" } } ``` `"shell"` action requires `command` key, which is an array of command and it's arguments. ### Mixing actions and side effects You can mix undoable and non-undoable actions. Actions are executed sequentially, hence depending on an order of actions you will end up losing ability to undo parts of that command. Instead of returning actions from functions that expect them, you can just read and write to files directly using `io.open()`. This will trigger a resource reload that will clear undo history. # Editor scripts and UI {#manuals:editor-scripts-ui} This manual explains how to create interactive UI elements in the editor using editor scripts written in Lua. To get started with editor scripts, see [Editor Scripts manual](#manuals:editor-scripts). You can find the full editor API reference [here](https://defold.com/ref/stable/editor-lua/). Currently, it's only possible to create interactive dialogs, though we want to expand the UI scripting support to the rest of the editor in the future. ## Hello world All UI-related functionality exists in the `editor.ui` module. Here is the simplest example of an editor script with a custom UI to get started: ```lua local M = {} function M.get_commands() return { { label = "Do with confirmation", locations = {"View"}, run = function() local result = editor.ui.show_dialog(editor.ui.dialog({ title = "Perform action?", buttons = { editor.ui.dialog_button({ text = "Cancel", cancel = true, result = false }), editor.ui.dialog_button({ text = "Perform", default = true, result = true }) } })) print('Perform action:', result) end } } end return M ``` This code snippet defines a **View → Do with confirmation** command. When you execute it, you will see the following dialog: Finally, after pressing `Enter` (or clicking on the `Perform` button), you'll see the following line in the editor console: ``` Perform action: true ``` ## Basic concepts ### Components The editor provides various UI **components** that can be composed to create the desired UI. By convention, all components are configured using a single table called **props**. The components themselves are not tables, but **immutable userdata** used by the editor for creating the UI. ### Props **Props** are tables that define inputs into components. Props should be treated as immutable: mutating the props table in-place will not cause the component to re-render, but using a different table will. UI is updated when the component instance receives a props table that is not shallow-equal to the previous one. ### Alignment When the component gets assigned some bounds in the UI, it will consume the whole space, though it does not mean that the visible part of the component will stretch. Instead, the visible part will take the space it needs, and then it will be aligned within the assigned bounds. Therefore, most built-in components define an `alignment` prop. For example, consider this label component: ```lua editor.ui.label({ text = "Hello", alignment = editor.ui.ALIGNMENT.RIGHT }) ``` The visible part is the `Hello` text, and it's aligned within the assigned component bounds: ## Built-in components The editor defines various built-in components that can be used together to build the UI. Components may be roughly grouped into 3 categories: layout, data presentation and input. ### Layout components Layout components are used for placing other components next to each other. Main layout components are **`horizontal`**, **`vertical`** and **`grid`**. These components also define props such as **padding** and **spacing**, where padding is an empty space from the edge of the assigned bounds to the content, and spacing is an empty space between children: Editor defines `small`, `medium` and `large` padding and spacing constants. When it comes to spacing, `small` is intended for spacing between different sub-elements of an individual UI element, `medium` is for spacing between individual UI elements, and `large` is a spacing between groups of elements. Default spacing is `medium`. A padding value of `large` means padding from the edges of the window to content, `medium` is padding from the edges of a significant UI element, and `small` is a padding from the edges of small UI elements like context menus and tooltips (not implemented yet). A **`horizontal`** container places its children one after another horizontally, always making the height every child fill the available space. By default, the width of every child is kept to a minimum, though it's possible to make it take as much space as possible by setting `grow` prop to `true` on a child. A **`vertical`** container is similar to horizontal, but with the axes switched. Finally, **`grid`** is a container component that lays out its children in a 2D grid, like a table. The `grow` setting in a grid applies to rows or columns, therefore it's set not on a child, but on column configuration table. Also, children in a grid may be configured to span multiple rows or columns with `row_span` and `column_span` props. Grids are useful for creating multi-input forms: ```lua editor.ui.grid({ padding = editor.ui.PADDING.LARGE, -- add padding around dialog edges columns = {% raw %}{{}, {grow = true}}{% endraw %}, -- make 2nd column grow children = { { editor.ui.label({ text = "Level Name", alignment = editor.ui.ALIGNMENT.RIGHT }), editor.ui.string_field({}) }, { editor.ui.label({ text = "Author", alignment = editor.ui.ALIGNMENT.RIGHT }), editor.ui.string_field({}) } } }) ``` The code above will produce the following dialog form: ### Data presentation components The editor defines 4 data presentation components: - **`label`** — text label, intended to be used with form inputs. - **`icon`** — an icon; currently, it can only be used for presenting a small set of predefined icons, but we intend to allow more icons in the future. - **`heading`** — text element intended for presenting a heading line of text in e.g. a form or a dialog. The `editor.ui.HEADING_STYLE` enum defines various heading styles that include HTML's `H1`-`H6` heading, as well as editor-specific `DIALOG` and `FORM`. - **`paragraph`** — text element intended for presenting a paragraph of text. The main difference with `label` is that paragraph supports word wrapping: if the assigned bounds are too small horizontally, the text will wrap, and possibly will be shortened with `"..."` if it can't fit in the view. ### Input components Input components are made for the user to interact with the UI. All input components support `enabled` prop to control if the interaction is enabled or not, and define various callback props that notify the editor script on interaction. If you create a static UI, it's enough to define callbacks that simply modify locals. For dynamic UIs and more advanced interactions, see [reactivity](#reactivity). For example, it's possible to create a simple static New File dialog like so: ```lua -- initial file name, will be replaced by the dialog local file_name = "" local create_file = editor.ui.show_dialog(editor.ui.dialog({ title = "Create New File", content = editor.ui.horizontal({ padding = editor.ui.PADDING.LARGE, spacing = editor.ui.SPACING.MEDIUM, children = { editor.ui.label({ text = "New File Name", alignment = editor.ui.ALIGNMENT.CENTER }), editor.ui.string_field({ grow = true, text = file_name, -- Typing callback: on_value_changed = function(new_text) file_name = new_text end }) } }), buttons = { editor.ui.dialog_button({ text = "Cancel", cancel = true, result = false }), editor.ui.dialog_button({ text = "Create File", default = true, result = true }) } })) if create_file then print("create", file_name) end ``` Here is a list of built-in input components: - **`string_field`**, **`integer_field`** and **`number_field`** are variations of a single-line text field that allow editing strings, integers, and numbers. - **`select_box`** is used for selecting an option from predefined array of options with a dropdown control. - **`check_box`** is a boolean input field with `on_value_changed` callback - **`button`** with `on_press` callback that gets invoked on button press. - **`external_file_field`** is a component intended for selecting a file path on the computer. It consists of a text field and a button that opens a file selection dialog. - **`resource_field`** is a component intended for selecting a resource in the project. All components except buttons allow setting an `issue` prop that displays the issue related to the component (either `editor.ui.ISSUE_SEVERITY.ERROR` or `editor.ui.ISSUE_SEVERITY.WARNING`), e.g.: ```lua issue = {severity = editor.ui.ISSUE_SEVERITY.WARNING, message = "This value is deprecated"} ``` When issue is specified, it changes how the input component looks, and adds a tooltip with the issue message. Here is a demo of all inputs with their issue variants: ### Dialog-related components To show a dialog, you need to use `editor.ui.show_dialog` function. It expects a **`dialog`** component that defines the main structure of Defold dialogs: `title`, `header`, `content` and `buttons`. Dialog component is a bit special: you can't use it as a child of another component, because it represents a window, not a UI element. `header` and `content` are usual components though. Dialog buttons are special too: they are created using **`dialog_button`** component. Unlike usual buttons, dialog buttons don't have `on_pressed` callback. Instead, they define a `result` prop with a value that will be returned by the `editor.ui.show_dialog` function when the dialog is closed. Dialog buttons also define `cancel` and `default` boolean props: button with a `cancel` prop is triggered when user presses `Escape` or closes the dialog with the OS close button, and `default` button is triggered when the user presses `Enter`. A dialog button may have both `cancel` and `default` props set to `true` at the same time. ### Utility components Additionally, the editor defines some utility components: - **`separator`** is a thin line used for delimiting blocks of content - **`scroll`** is a wrapper component that shows scroll bars when the wrapped component does not fit in the assigned space ## Reactivity Since components are **immutable userdata**, it's impossible to change them after they are created. How to make the UI change over time then? The answer: **reactive components**. The editor scripting UI draws inspiration from [React](https://react.dev/) library, so knowing about reactive UI and React hooks will help. In the most simple terms, a reactive component is a component with a Lua function that receives data (props) and returns view (another component). Reactive component function may use **hooks**: special functions in the `editor.ui` module that add reactive features to your components. By convention, all hooks have a name that starts with `use_`. To create a reactive component, use `editor.ui.component()` function. Let's have a look at this example — a New File dialog that only allows creating a file if the entered file name is not empty: ```lua -- 1. dialog is a reactive component local dialog = editor.ui.component(function(props) -- 2. the component defines a local state (file name) that defaults to empty string local name, set_name = editor.ui.use_state("") return editor.ui.dialog({ title = props.title, content = editor.ui.vertical({ padding = editor.ui.PADDING.LARGE, children = { editor.ui.string_field({ value = name, -- 3. typing + Enter updates the local state on_value_changed = set_name }) } }), buttons = { editor.ui.dialog_button({ text = "Cancel", cancel = true }), editor.ui.dialog_button({ text = "Create File", -- 4. creation is enabled when the name exists enabled = name ~= "", default = true, -- 5. result is the name result = name }) } }) end) -- 6. show_dialog will either return non-empty file name or nil on cancel local file_name = editor.ui.show_dialog(dialog({ title = "New File Name" })) if file_name then print("create " .. file_name) else print("cancelled") end ``` When you execute a menu command that runs this code, the editor will show a dialog with disabled `"Create File"` dialog at the start, but, when you type a name and press `Enter`, it will become enabled: So, how does it work? On the very first render, `use_state` hook creates a local state associated with the component and returns it with a setter for the state. When the setter function is invoked, it schedules a component re-render. On subsequent re-renders, the component function is invoked again, and `use_state` returns the updated state. New view component returned by the component function is then diffed against the old one, and the UI is updated where the changes were detected. This reactive approach greatly simplifies building interactive UIs and keeping them in sync: instead of explicitly updating all affected UI components on user input, the view is defined as a pure function of the input (props and local state), and the editor handles all the updates itself. ### Rules of reactivity The editor expects reactive function components to behave nicely for them to work: 1. Component functions must be pure. There is no guarantee on when or how often the component function will be invoked. All side-effects should be outside of rendering, e.g. in callbacks 2. Props and local state must be immutable. Don't mutate props. If your local state is a table, don't mutate it in-place, but create a new one and pass it to the setter when the state needs to change. 3. Component functions must call the same hooks in the same order on every invocation. Don't call hooks inside loops, in conditional blocks, after early returns etc. It is a best practice to call hooks in the beginning of the component function, before any other code. 4. Only call hooks from component functions. Hooks work in a context of a reactive component, so it's only allowed to call them in the component function (or another function called directly by the component function). ### Hooks If you are familiar with [React](https://react.dev/), you will notice that hooks in the editor have slightly different semantics when it comes to hook dependencies. The editor defines 2 hooks: **`use_memo`** and **`use_state`**. ### **`use_state`** Local state can be created in 2 ways: with a default value or with an initializer function: ```lua -- default value local enabled, set_enabled = editor.ui.use_state(true) -- initializer function + args local id, set_id = editor.ui.use_state(string.lower, props.name) ``` Similarly, setter can be invoked with a new value or with an updater function: ```lua -- updater function local function increment_by(n, by) return n + by end local counter = editor.ui.component(function(props) local count, set_count = editor.ui.use_state(0) return editor.ui.horizontal({ spacing = editor.ui.SPACING.SMALL, children = { editor.ui.label({ text = tostring(count), alignment = editor.ui.ALIGNMENT.LEFT, grow = true }), editor.ui.text_button({ text = "+1", on_pressed = function() set_count(increment_by, 1) end }), editor.ui.text_button({ text = "+5", on_pressed = function() set_count(increment_by, 5) end }) } }) end) ``` Finally, the state may be **reset**. The state is reset when any of the arguments to `editor.ui.use_state()` change, checked with `==`. Because of this, you must not use literal tables or literal initializer functions as arguments to `use_state` hook: this will cause the state to reset on every re-render. To illustrate: ```lua -- ❌ BAD: literal table initializer causes state reset on every re-render local user, set_user = editor.ui.use_state({ first_name = props.first_name, last_name = props.last_name}) -- ✅ GOOD: use initializer function outside of component function to create table state local function create_user(first_name, last_name) return { first_name = first_name, last_name = last_name} end -- ...later, in component function: local user, set_user = editor.ui.use_state(create_user, props.first_name, props.last_name) -- ❌ BAD: literal initializer function causes state reset on every re-render local id, set_id = editor.ui.use_state(function() return string.lower(props.name) end) -- ✅ GOOD: use referenced initializer function to create the state local id, set_id = editor.ui.use_state(string.lower, props.name) ``` ### **`use_memo`** You can use `use_memo` hook to improve performance. It is common to perform some computations in the render functions, e.g. to check if the user input is valid. `use_memo` hook can be used in cases where checking if arguments to the computation function have changed is cheaper than invoking the computation function. The hook will call the computation function on first render, and will re-use the computed value on subsequent re-renders if all the arguments to `use_memo` are unchanged: ```lua -- validation function outside of component function local function validate_password(password) if #password < 8 then return false, "Password must be at least 8 characters long." elseif not password:match("%l") then return false, "Password must include at least one lowercase letter." elseif not password:match("%u") then return false, "Password must include at least one uppercase letter." elseif not password:match("%d") then return false, "Password must include at least one number." else return true, "Password is valid." end end -- ...later, in component function local username, set_username = editor.ui.use_state('') local password, set_password = editor.ui.use_state('') local valid, message = editor.ui.use_memo(validate_password, password) ``` In this example, password validation will run on every password change (e.g. on typing in a password field), but not when the username is changed. Another use-case for `use_memo` is creating callbacks that are then used on input components, or when a locally-created function is used as a prop value for another component — this prevents unnecessary re-renders. # Debugging game logic {#manuals:debugging-game-logic} 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 cause of bugs in your game logic or help analyze performance issues. ## Print and visual debugging The simplest way to debug your game in Defold is to use [print debugging](http://en.wikipedia.org/wiki/Debugging#Techniques). Use `print()` or [`pprint()`](https://defold.com/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 and to the [game log](#manuals:debugging-game-and-system-logs). 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 -- 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 colored text on the screen local color_green = vmath.vector4(0, 1, 0, 1) msg.post("@render:", "draw_debug_text", { text = "Custom color", position = vmath.vector3(200, 180, 0), color = color_green }) -- 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 }) ``` The visual debug messages adds data to the rendering pipeline and is drawn as part of the regular render pipeline. * `"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/debug/always_on_top.font` that uses the `/builtins/fonts/debug/always_on_top_font.material` material. * `"draw_debug_text"` is the same as `"draw_text"`, but it's rendered in a custom color. Note that you probably want to update this data every frame so posting the messages in the `update()` function is a good idea. ## Running the debugger To run the debugger, select `Debug ▸ Start/Attach` which either starts up the game with the debugger attached or attaches the debugger to an already running game. 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 `Debug` menu: Break : 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: Continue : 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: Stop : Stop the debugger. Pressing this button will immediately stop the debugger, detach it from the game and terminate the running game. Step Over : 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()`: 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. Step Into : 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()`: Step Out : 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. 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. To set or clear a breakpoint, click in the column just right of the line numbers in the code editor. You can also select `Edit ▸ Toggle Breakpoint` from the menu. Disabling and enabling breakpoints : Breakpoints can be temporarily disabled without removing them. When disabled, they are ignored during execution but can be re-enabled at any time. Right-click it in the code editor gutter, then toggle the Enabled checkbox. Disabled breakpoints appear hollowed out to indicate they are inactive. Setting conditional breakpoints : You can configure your breakpoint to contain a condition that needs to evaluate to true for the breakpoint to trigger. The condition can access local variables available at the line during code execution. To edit the breakpoint condition, right-click in the column just right of the line numbers in the code editor, or select `Edit ▸ Edit Breakpoint` from the menu. 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 `Enter` to evaluate them: It is currently not possible to modify variables through the evaluator. Detaching the debugger : Select `Debug ▸ Detach Debugger` to detach the debugger from the game. It will continue running immediately. ## Breakpoints Tab When working with multiple breakpoints across different scripts, the Breakpoints tab provides a centralized view for managing all your breakpoints in one place. ##### Individual Breakpoint Controls For working with individual breakpoints: - Click the red trash icon to remove a breakpoint - Double-click the row (outside the condition area) to navigate to that line in the Code View - Double-click the condition cell or click the pen icon to edit conditional breakpoints - Click the X clear button when hovering over a condition cell to clear the condition ##### Batch Operations Select multiple breakpoints using Ctrl/Cmd+click or Shift+click, then right-click to perform bulk actions. You can edit conditions across several breakpoints simultaneously, toggle their active state, or remove them entirely. The toolbar buttons allow you to enable, disable, or toggle all breakpoints at once, useful when you want to run your game without stopping but don't want to lose their positions. You can also remove all when you're done with your debugging session. ## Lua debug library 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 in [the chapter about the Debug Library in the Lua manual](http://www.lua.org/pil/contents.html#23). ## Debugging checklist If you encounter an error or if your game does not behave like expected, here is a debugging checklist: 1. Check the console output and verify that there are no runtime errors. 2. Add `print` statements to your code to verify that the code is actually running. 3. If it's not running, check that you have done the proper setup in the editor required for the code to run. Is the script added to the right game object? Have your script acquired input focus? Are the input-triggers correct? Is the shader code added to the material? Etc. 4. If your code is depending on the values of variables (in an if-statement, for example), either `print` those values where they are used or checked, or inspect them with the debugger. Sometimes finding a bug can be a hard and time consuming process, requiring you to go through your code bit by bit, checking everything and narrowing down the faulty code and eliminating sources of error. This is best done by a method called "divide and conquer": 1. Figure out which half (or less) of the code that must contain the bug. 2. Again, figure out which half, of that half, must contain the bug. 3. Continue narrowing down the code that must cause the bug until you find it. Happy hunting! ## Debugging problems with physics If you have problems with physics and collisions aren't working as expected it is recommended to enable physics debugging. Check the *Debug* checkbox in the *Physics* section of the *game.project* file: When this checkbox is enabled Defold will draw all collision shapes and contact points of collisions: # Editor preferences {#manuals:editor-preferences} You can modify the settings of the editor from the Preferences window. The preferences window is opened from the `File -> Preferences` menu. ## General Load External Changes on App Focus : Enables scanning for external changes when the editor receives focus. Open Bundle Target Folder : Enables opening of the target bundle folder after bundling process is done. Enable Texture Compression : Enables [texture compression](#manuals:texture-profiles) for all builds made from the editor. Escape Quits Game : Shutdown a running build of your game using the `Esc` key. Track Active Tab in Asset Browser : The file edited in selected tab in the *Editor* pane will be selected in the Asset Browser (also known as the *Asset* pane). Lint Code on Build : Enables [code linting](#manuals:writing-code) when the project is built. This option is enabled by default, but can be disabled if the linting in a large project takes too much time. Engine Arguments : Arguments that will be passed to the dmengine executable when the editor builds and runs. Use one argument per line. For example: ``` --config=bootstrap.main_collection=/my dir/1.collectionc --verbose --graphics-adapter=vulkan ``` ## Code Custom Editor : Absolute path to an external editor. On macOS it should be the path to the executable inside the .app (e.g. `/Applications/Atom.app/Contents/MacOS/Atom`). Open File : The pattern used by the custom editor to specify which file to open. The pattern `{file}` will be replaced by the filename to open. Open File at Line : The pattern used by the custom editor to specify which file to open and on which line number. The pattern `{file}` will be replaced by the filename to open and `{line}` by the line number. Code editor font : Name of a system installed font to use in the code editor. Zoom on Scroll : Whether to change the font size when scrolling in the code editor while holding Cmd/Ctrl button. ### Open script files in Visual Studio Code To open script files from the Defold Editor directly in Visual Studio Code, you must set the following settings by specifying the path to the executable file: - MacOS: `/Applications/Visual Studio Code.app/Contents/MacOS/Electron` - Linux: `/usr/bin/code` - Windows: `C:\Program Files\Microsoft VS Code\Code.exe` Set these parameters to open specific files and lines: - Open File: `. {file}` - Open File at Line: `. -g {file}:{line}` The `.` character here is required to open the entire workspace, not an individual file. ## Extensions Build Server : URL to the build server used when building a project containing [native extensions](#manuals:extensions). It is possible to add a username and access token to the URL for authenticated access to the build server. Use the following notation to specify the username and access token: `username:token@build.defold.com`. Authenticated access is required for Nintendo Switch builds and when running your own build server instance with authentication enabled ([refer to the build server documentation](https://github.com/defold/extender/blob/dev/README_SECURITY.md) for more information). The username and password can also be set as the system environment variables `DM_EXTENDER_USERNAME` and `DM_EXTENDER_PASSWORD`. Build Server Username : username for authentication. Build Server Password : password for authentication, will be stored encrypted in the preferences file. Build Server Headers : additional headers to the build server when building native extensions. It's important for using CloudFlare service or similar services with extender. ## Tools ADB path : Path to [ADB](https://developer.android.com/tools/adb) command line tool installed on this system. If you have ADB installed on your system, the Defold editor will use it to install and run bundled Android APKs to a connected Android Device. By default, the editor checks if ADB is installed in well-known locations, so you only need to specify the path if you have ADB installed in a custom location. ios-deploy path : Path to [ios-deploy](https://github.com/ios-control/ios-deploy) command line tools installed on this system (only relevant for macOS). Similarly to the ADB path, the Defold editor will use this tool to install and run bundled iOS applications on a connected iPhone. By default, the editor checks if ios-deploy is installed in well-known locations, so you only need to specify the path if you use a custom installation of ios-deploy. ## Keymap You can configure the editor shortcuts, both adding custom and removing the built-in ones. Use context menu on individual commands in the shortcut table to edit the shortcuts, or double-click/press `Enter` to open a new shortcut popup. Some shortcuts might have warnings: they are displayed using orange color. Hover over the shortcut to see the warning. Typical warnings are: - typeable shortcuts: the selected shortcut is typeable in a text inputs. Make sure the command is off in the code editing / text input contexts. - conflicts: the same shortcut is assigned to multiple different commands. Make sure at most one command is enabled when the shortcut is invoked, otherwise the editor will execute one of the assigned commands in an undefined manner. # Refactoring {#manuals:refactoring} Refactoring refers to the process of restructuring existing code and assets. During the development of a project, the need to change or move things around often surfaces: names need to change to adhere to naming conventions or to improve clarity and code or asset files need to move to a more logical place in the project hierarchy. Defold helps you refactor efficiently by keeping track of how assets are used. It automatically updates references to assets that are renamed and/or moved. As a developer, you should feel free in your work. Your project is a flexible structure that you can change at will without fearing that everything will break and fall to pieces. Automatic refactoring will only work if changes are made from within the editor. If you rename or move a file outside the editor any references to this file will not get automatically changed. However, if you break a reference by, for instance, deleting an asset, the editor can't resolve the problem, but will provide helpful error signals. For example, if you delete an animation from an atlas and that animation is in use somewhere, Defold will signal an error when you try to start the game. The editor will also mark where the errors occur to help you quickly locate the problem: Build errors appear in the *Build Errors* pane at the bottom of the editor. `Double clicking` an error takes you to the location of the problem. # Editor styling {#manuals:editor-styling} You can modify the colors, typography and other visual aspects of the editor using a custom stylesheet: * Create a folder named `.defold` in your user home directory. * On Windows `C:\Users\**Your Username**\.defold` * On macOS `/Users/**Your Username**/.defold` * On Linux `~/.defold` * Create a `editor.css` file in the `.defold` folder The editor will on startup load your custom stylesheet and apply it on top of the default style. The editor uses JavaFX for the user interface and the stylesheets are almost identical to the CSS files used in a browser to apply style attributes to the elements of a webpage. The default stylesheets for the editor are [available for inspection on GitHub](https://github.com/defold/defold/tree/editor-dev/editor/styling/stylesheets/base). ## Changing color The default colors are defined in [`_palette.scss`](https://github.com/defold/defold/blob/editor-dev/editor/styling/stylesheets/base/_palette.scss) and look like this: ``` * { // Background -df-background-darker: derive(#212428, -10%); -df-background-dark: derive(#212428, -5%); -df-background: #212428; -df-background-light: derive(#212428, 10%); -df-background-lighter: derive(#212428, 20%); // Component -df-component-darker: derive(#464c55, -20%); -df-component-dark: derive(#464c55, -10%); -df-component: #464c55; -df-component-light: derive(#464c55, 10%); -df-component-lighter: derive(#464c55, 20%); // Text & icons -df-text-dark: derive(#b4bac1, -10%); -df-text: #b4bac1; -df-text-selected: derive(#b4bac1, 20%); and so on... ``` The basic theme is divided into three groups of colors (with darker and lighter variants): * Background color - background color in panels, windows, dialogs * Component color - buttons, scroll bar handles, text field outlines * Text color - text and icons As an example, if you add this to your custom `editor.css` stylesheet in `.defold` folder in user home: ``` * { -df-background-darker: derive(#0a0a42, -10%); -df-background-dark: derive(#0a0a42, -5%); -df-background: #0a0a42; -df-background-light: derive(#0a0a42, 10%); -df-background-lighter: derive(#0a0a42, 20%); } ``` You will get the following look in your editor: ## Changing fonts The editor uses two fonts: `Dejavu Sans Mono` for code and mono spaced text (errors) and `Source Sans Pro` for the rest of the UI. The font definitions are mainly found in [`_typography.scss`](https://github.com/defold/defold/blob/editor-dev/editor/styling/stylesheets/base/_typography.scss) and look like this: ``` @font-face { src: url("SourceSansPro-Light.ttf"); } @font-face { src: url("DejaVuSansMono.ttf"); } $default-font-mono: 'Dejavu Sans Mono'; $default-font: 'Source Sans Pro'; $default-font-bold: 'Source Sans Pro Semibold'; $default-font-italic: 'Source Sans Pro Italic'; $default-font-light: 'Source Sans Pro Light'; .root { -fx-font-size: 13px; -fx-font-family: $default-font; } Text.strong { -fx-font-family: $default-font-bold; } and so on... ``` The main font is defined in a root element which makes it quite easy to replace the font in most places. Add this to your `editor.css`: ``` @import url('https://fonts.googleapis.com/css2?family=Architects+Daughter&display=swap'); .root { -fx-font-family: "Architects Daughter"; } ``` You will get the following look in your editor: It is also possible to use a local font instead of a web font: ``` @font-face { font-family: 'Comic Sans MS'; src: local("cs.ttf"); } .root { -fx-font-family: 'Comic Sans MS'; } ``` The code editor font is defined separately in the editor Preferences! # Building blocks {#manuals:building-blocks} At the core of Defold's design are a few concepts that are very important to get a good grip on. This manual explains what the building blocks of Defold consist of. After having read this manual, move on to the [addressing manual](#manuals:addressing) and the [message passing manual](#manuals:message-passing). There are also a set of [tutorials](/tutorials/getting-started) available from within the editor to get you up and running quickly. There are three basic types of building blocks that you use to construct a Defold game: Collection : A collection is a file used to structure your game. In collections you build hierarchies of game objects and other collections. They are typically used to structure game levels, groups of enemies or characters built out of several game objects. Game object : A game object is a container with an id, position, rotation and scale. It is used to contain components. They are typically used to create player characters, bullets, the game’s rule system or a level loader/e. Component : Components are entities that are put in game object to give them visual, audible and/or logic representation in the game. They are typically used to create character sprites, script files, add sound effects or add particle effects. ## Collections Collections are tree structures that hold game objects and other collections. A collection is always stored on file. When the Defold engine starts, it loads a single _bootstrap collection_ as specified in the *game.project* settings file. The bootstrap collection is often named "main.collection" but you are free to use any name you like. A collection can contain game objects and other collections (by reference to the sub-collection's file), nested arbitrarily deep. Here is an example file called "main.collection". It contains one game object (with the id "can") and one sub-collection (with the id "bean"). The sub-collection, in turn, contains two game objects: "bean" and "shield". Notice that the sub-collection with id "bean" is stored in its own file, called "/main/bean.collection" and is only referenced in "main.collection": You cannot address collections themselves since there are no runtime objects corresponding to the "main" and "bean" collections. However, you sometimes need to use the identity of a collection as part of the _path_ to a game object (See the [addressing manual](#manuals:addressing) for details): ```lua -- file: can.script -- get position of the "bean" game object in the "bean" collection local pos = go.get_position("bean/bean") ``` A collection is always added to another collection as a reference to a collection file: `Right-click` the collection in the *Outline* view and select `Add Collection File`. ## Game objects Game objects are simple objects that each have a separate lifespan during the execution of your game. Game objects have a position, rotation, and scale that each of which can be manipulated and animated at runtime. ```lua -- animate X position of "can" game object go.animate("can", "position.x", go.PLAYBACK_LOOP_PINGPONG, 100, go.EASING_LINEAR, 1.0) ``` Game objects can be used empty (as position markers, for instance) but are usually equipped with various components, like sprites, sounds, scripts, models, factories and more. Game objects are either created in the editor, placed in collection files, or dynamically spawned at run-time through _factory_ components. Game objects are either added in-place in a collection, or added to a collection as a reference to a game object file: `Right-click` the collection in the *Outline* view and select `Add Game Object` (add in-place) or `Add Game Object File` (add as file reference). ## Components Components are used to give specific expression and/or functionality to game objects. Components have to be contained inside game objects and are affected by the position, rotation and scale of the game object that contains the component: Many components have type specific properties that can be manipulated and there are component type specific functions available for interacting with them in runtime: ```lua -- disable the can "body" sprite msg.post("can#body", "disable") -- play "hoohoo" sound on "bean" in 1 second sound.play("bean#hoohoo", { delay = 1, gain = 0.5 } ) ``` Components are either added in-place in a game object, or added to a game object as a reference to a component file: `Right-click` the game object in the *Outline* view and select `Add Component` (add in-place) or `Add Component File` (add as file reference). In most cases it makes most sense to create components in-place, but the following component types must be created in separate resource files before being added by reference to a game object: * Script * GUI * Particle FX * Tile Map Refer to the [component overview](#manuals:components) for a list of all available component types. ## Objects added in-place or by reference When you create a collection, game object or component _file_, you create what we call a prototype (also known as "prefabs" or "blueprints" in other engines). This only adds a file to the project file structure, nothing is added to your running game. To add an instance of a collection, game object or component based on a prototype file, you add an instance of it in one of your collection files. You can see what file an object instance is based on in the outline view. The file "main.collection" contains three instances that are based on files: 1. The "bean" sub-collection. 2. The "bean" script component in the "bean" game object in the "bean" sub-collection. 3. The "can" script component in the "can" game object. The benefit of creating prototype files becomes apparent when you have multiple instances of a game object or collection and wish to change all of them: By changing the prototype file, any instance that uses that file will immediately be updated. Here the sprite image of the prototype file is changed and immediately all instances using the file are updated: ## Childing game objects In a collection file, you can build hierarchies of game objects so that one or more game objects are children to a single parent game object. By simply `dragging` one game object and `dropping` it onto another, the dragged game object becomes a child of the target: Object parent-child hierarchies is a dynamic relation affecting how objects react to transformations. Any transformation (movement, rotation or scaling) applied to an object will in turn be applied to the object’s children, both in the editor and in runtime: Conversely, a child's translations are done in the local space of the parent. In the editor, you can choose to edit a child game object in the local space or world space by selecting `Edit ▸ World Space` (the default) or `Edit ▸ Local Space`. It is also possible to alter an object’s parent in run-time by sending a `set_parent` message to the object. ```lua local parent = go.get_id("bean") msg.post("child_bean", "set_parent", { parent_id = parent }) ``` A common misunderstanding is that a game object's place in the collection hierarchy changes when it becomes part of a parent-child hierarchy. However, these are two very different things. Parent-child hierarchies dynamically alter the scene graph, which allows objects to be visually attached to each other. The only thing that dictates a game object's address is its place in the collection hierarchy. The address is static throughout the lifetime of the object. # Addressing {#manuals:addressing} Code that controls a running game must be able to reach every object and component in order to move, scale, animate, delete and manipulate what the player sees and hears. Defold's addressing mechanism makes this possible. ## Identifiers Defold uses addresses (or URLs, but let's ignore that for now) to refer to game objects and components. These addresses consist of identifiers. The following are all examples of how Defold uses addresses. Through this manual we are going to examine in detail how they work: ```lua local id = factory.create("#enemy_factory") label.set_text("my_gameobject#my_label", "Hello World!") local pos = go.get_position("my_gameobject") go.set_position(pos, "/level/stuff/other_gameobject") msg.post("#", "hello_there") local id = go.get_id(".") ``` Let's start with a very simple example. Suppose that you have a game object with a single sprite component. You also have a script component to control the game object. The setup in the editor would look something like this: Now you want to disable the sprite when the game starts, so you can make it appear later. That is easily done by putting the following code in "controller.script": ```lua function init(self) msg.post("#body", "disable") -- <1> end ``` 1. Don't worry if you're puzzled by the '#' character. We'll get to that soon. This will work as expected. When the game starts, the script component *addresses* the sprite component by its identifier "body" and uses that address to send it a *message* with the "disable". The effect of this special engine message is that the sprite component hides the sprite graphics. Schematically, the setup looks like this: The identifiers in the setup are arbitrary. Here we have chosen to give the game object the identifier "bean", its sprite component has been named "body", and the script component that controls the character has been named "controller". If you don't choose a name, the editor will. Whenever you create a new game object or component in the editor, a unique *Id* property is automatically set. - Game objects automatically get an id called "go" with an enumerator ("go2", "go3" etc). - Components get an id corresponding to the component type ("sprite", "sprite2" etc). You can stick to these automatically assigned names if you want to, but we encourage you to change the identifiers into good, descriptive names. Now, let's add another sprite component and give the bean a shield: The new component must be uniquely identified within the game object. If you would give it the name "body" the script code would be ambiguous as to which sprite it should send the "disable" message. Therefore we pick the unique (and descriptive) identifier "shield". Now we can enable and disable the "body" and "shield" sprites at will. If you do try to use an identifier more than once, the editor will signal an error so this is never a problem in practice: Now, let's look at what happens if you add more game objects. Suppose you want to pair two "beans" into a small team. You decide to call one of the bean game objects "bean" and the other one "buddy". Furthermore, when "bean" has been idle for a while, it should tell "buddy" to start dancing. That is done by sending a custom message called "dance" from the "controller" script component in "bean" to the "controller" script in "buddy": There are two separate components named "controller", one in each game object but this is perfectly legal since each game object creates a new naming context. Since the addressee of the message is outside the game object sending the message ("bean"), the code needs to specify which "controller" should receive the message. It needs to specify both the target game object id as well as the component id. The full address to the component becomes `"buddy#controller"` and this address consists of two separate parts. - First come the identity of the target game object ("buddy"), - then follows the game object/component separator character ("#"), - and finally you write the identity of the target component ("controller"). Going back to the previous example with a single game object we see that by leaving out the game object identifier part of the target address, the code can address components in the *current game object*. For example, `"#body"` denotes the address to the component "body" in the current game object. This is very useful because this code will work in *any* game object, as long as there is a "body" component present. ## Collections Collections makes it possible to create groups, or hierarchies, of game objects and reuse them in a controlled way. You use collection files as templates (or "prototypes" or "prefabs") in the editor when you populate your game with content. Suppose that you want to create a great number of bean/buddy teams. A good way to do that is to create a template in a new *collection file* (name it "team.collection"). Build the team game objects in the collection file and save it. Then put an instance of that collection file's contents in your main bootstrap collection and give the instance an identifier (name it "team_1"): With this structure, the "bean" game object can still refer to the "controller" component in "buddy" by the address `"buddy#controller"`. And if you add a second instance of "team.collection" (name it "team_2"), the code running inside the "team_2" script components will work just as well. The "bean" game object instance from collection "team_2" can still address the "controller" component in "buddy" by the address `"buddy#controller"`. ## Relative addressing The address `"buddy#controller"` works for the game objects in both collections because it is a *relative* address. Each of the collections "team_1" and "team_2" creates a new naming context, or "namespace" if you will. Defold avoids naming collisions by taking the naming context a collection creates into consideration for addressing: - Within the naming context "team_1", the game objects "bean" and "buddy" are uniquely identified. - Similarly, within the naming context "team_2", the game objects "bean" and "buddy" are also uniquely identified. Relative addressing works by automatically prepending the current naming context when resolving a target address. This is again immensely useful and powerful because you can create groups of game objects with code and reuse those efficiently throughout the game. ### Shorthands Defold provides two handy shorthands that you can use to send messages without specifying a complete URL: `.` : Shorthand resolving to the current game object. `#` : Shorthand resolving to the current component. For example: ```lua -- Let this game object acquire input focus msg.post(".", "acquire_input_focus") ``` ```lua -- Post "reset" to the current script msg.post("#", "reset") ``` ## Game object paths To correctly understand the naming mechanism, let's look at what happens when you build and run the project: 1. The editor reads the bootstrap collection ("main.collection") and all its content (game objects and other collections). 2. For each static game object, the compiler creates an identifier. These are built as "paths" starting at the bootstrap root, down the collection hierarchy to the object. A '/' character is added at each level. For our example above, the game will run with the following 4 game objects: - /team_1/bean - /team_1/buddy - /team_2/bean - /team_2/buddy Identities are stored as hashed values. The runtime also stores the hash state for each collection identity which is used to continue hashing relative string to an absolute id. In runtime, the collection grouping does not exist. There is no way to find out what collection a specific game object belonged to before compilation. Nor is it possible to manipulate all the objects in a collection at once. If you need to do such operations, you can easily do the tracking yourself in code. Each object's identifier is static, it is guaranteed to stay fixed throughout the object's lifetime. This means that you can safely store the identity of an object and use it later. ## Absolute addressing It is possible to use the full identifiers described above when addressing. In most cases relative addressing is preferred since it allows for content reuse, but there are cases where absolutely addressing becomes necessary. For example, suppose that you want an AI manager that tracks the state of each bean object. You want beans to report their active status to the manager, and the manager makes tactical decisions and gives orders to the beans based on their status. It would make perfect sense in this case to create a single manager game object with a script component and place that alongside the team collections in the bootstrap collection. Each bean is then responsible for sending status messages to the manager: "contact" if it spots an enemy or "ouch!" if it is hit and takes damage. For this to work, the bean controller script uses absolute addressing to send messages to the component "controller" in "manager". Any address that starts with a '/' will be resolved from the root of the game world. This corresponds to the root of the *bootstrap collection* that is loaded on game start. The absolute address of the manager script is `"/manager#controller"` and this absolute address will resolve to the right component no matter where it is used. ## Hashed identifiers The engine stores all identifiers as hashed values. All functions that take as argument a component or a game object accepts a string, hash or a URL object. We have seen how to use strings for addressing above. When you get the identifier of a game object, the engine will always return an absolute path identifier that is hashed: ```lua local my_id = go.get_id() print(my_id) --> hash: [/path/to/the/object] local spawned_id = factory.create("#some_factory") print(spawned_id) --> hash: [/instance42] ``` You can use such an identifier in place of a string id, or construct one yourself. Note though that a hashed id corresponds to the path of the object, i.e. an absolute address: The reason relative addresses must be given as strings is because the engine will compute a new hash id based on the hash state of the current naming context (collection) with the given string added to the hash. ```lua local spawned_id = factory.create("#some_factory") local pos = vmath.vector3(100, 100, 0) go.set_position(pos, spawned_id) local other_id = hash("/path/to/the/object") go.set_position(pos, other_id) -- This will not work! Relative addresses must be given as strings. local relative_id = hash("my_object") go.set_position(pos, relative_id) ``` ## URLs To complete the picture, let's look at the full format of Defold addresses: the URL. A URL is an object, usually written as a specially formatted string. A generic URL consists of three parts: `[socket:][path][#fragment]` socket : Identifies the game world of the target. This is important when working with [Collection Proxies](#manuals:collection-proxy) and is then used to identify the _dynamically loaded collection_. path : This part of the URL contains the full id of the target game object. fragment : The identity of the target component within the specified game object. As we have seen above, you can leave out some, or most of this information in the majority of cases. You almost never need to specify the socket, and you often, but not always, have to specify the path. In those cases when you do need to address things in another game world then you need to specify the socket part of the URL. For instance, the full URL string for the "controller" script in the "manager" game object above is: `"main:/manager#controller"` and the buddy controller in team_2 is: `"main:/team_2/buddy#controller"` We can send messages to them: ```lua -- Send "hello" to the manager script and team buddy bean msg.post("main:/manager#controller", "hello_manager") msg.post("main:/team_2/buddy#controller", "hello_buddy") ``` ## Constructing URL objects URL objects can also be constructed programmatically in Lua code: ```lua -- Construct URL object from a string: local my_url = msg.url("main:/manager#controller") print(my_url) --> url: [main:/manager#controller] print(my_url.socket) --> 786443 (internal numeric value) print(my_url.path) --> hash: [/manager] print(my_url.fragment) --> hash: [controller] -- Construct URL from parameters: local my_url = msg.url("main", "/manager", "controller") print(my_url) --> url: [main:/manager#controller] -- Build from empty URL object: local my_url = msg.url() my_url.socket = "main" -- specify by valid name my_url.path = hash("/manager") -- specify as string or hash my_url.fragment = "controller" -- specify as string or hash -- Post to target specified by URL msg.post(my_url, "hello_manager!") ``` # Message passing {#manuals:message-passing} Message passing is a mechanism for Defold game objects to communicate with each other. This manual assumes that you have a basic understanding of Defold's [addressing mechanism](#manuals:addressing) and [basic building blocks](#manuals:building-blocks). Defold does not do object orientation in the sense that you define your application by setting up class hierarchies with inheritance and member functions in your objects (like Java, C++ or C#). Instead, Defold extends Lua with a simple and powerful object oriented design where object state is kept internally in script components, accessible through the `self` reference. Objects can furthermore be fully decoupled with asynchronous message passing as means of communication between objects. ## Usage examples Let's first look at a few simple usage examples. Suppose that you are building a game consisting of: 1. A main bootstrap collection containing a game object with a GUI component (the GUI consists of a minimap and a score counter). There is also a collection with id "level". 2. The collection named "level" contains two game objects: one hero player character and one enemy. The content of this example lives in two separate files. There is one file for the main bootstrap collection and one for the collection with the id "level". However, file names _do not matter_ in Defold. The identity you assign to instances does. The game contains a few simple mechanics that require communication between the objects: ① The hero punches the enemy : As part of this mechanic, a `"punch"` message is sent from the "hero" script component to the "enemy" script component. Since both objects live in the same place in the collection hierarchy, relative addressing is preferred: ```lua -- Send "punch" from the "hero" script to "enemy" script msg.post("enemy#controller", "punch") ``` There is only a single strength punch move in the game so the message does not need to contain any more information than its name, "punch". In the script component of the enemy, you create a function to receive the message: ```lua function on_message(self, message_id, message, sender) if message_id == hash("punch") then self.health = self.health - 100 end end ``` In this case, the code only looks at the name of the message (sent as a hashed string in the parameter `message_id`). The code does not care about message data nor the sender---*anyone* sending the message "punch" will inflict damage on the poor enemy. ② Hero gaining score : Whenever the player defeats an enemy, the player score increases. A `"update_score"` message is also sent from the "hero" game object's script component to the "gui" component of the "interface" game object. ```lua -- Enemy defeated. Increase score counter by 100. self.score = self.score + 100 msg.post("/interface#gui", "update_score", { score = self.score }) ``` In this case it's not possible to write a relative address since "interface" is at the root of the naming hierarchy and "hero" is not. The message is sent to the GUI component that has a script attached to it, so it can react to the message accordingly. Messages can be sent freely between scripts, GUI scripts and render scripts. The message `"update_score"` is coupled with score data. The data is passed as a Lua table in the `message` parameter: ```lua function on_message(self, message_id, message, sender) if message_id == hash("update_score") then -- set the score counter to new score local score_node = gui.get_node("score") gui.set_text(score_node, "SCORE: " .. message.score) end end ``` ③ Enemy position on the minimap : The player has a minimap on screen to help locate and track enemies. Each enemy is responsible for signalling its position by sending an `"update_minimap"` message to the "gui" component in the "interface" game object: ```lua -- Send the current position to update the interface minimap local pos = go.get_position() msg.post("/interface#gui", "update_minimap", { position = pos }) ``` The GUI script code needs to track the position of each enemy, and if the same enemy sends a new position, the old should be replaced. The sender of the message (passed in parameter `sender`) can be used to key a Lua table with positions: ```lua function init(self) self.minimap_positions = {} end local function update_minimap(self) for url, pos in pairs(self.minimap_positions) do -- update position on map ... end end function on_message(self, message_id, message, sender) if message_id == hash("update_score") then -- set the score counter to new score local score_node = gui.get_node("score") gui.set_text(score_node, "SCORE: " .. message.score) elseif message_id == hash("update_minimap") then -- update the minimap with new positions self.minimap_positions[sender] = message.position update_minimap(self) end end ``` ## Sending messages The mechanics of sending a message are, as we have seen above, very simple. You call the function `msg.post()` which posts your message to the message queue. Then, each frame, the engine runs through the queue and delivers each message to its target address. For some system messages (like `"enable"`, `"disable"`, `"set_parent"` etc) the engine code handles the message. The engine also produces some system messages (like `"collision_response"` on physics collisions) that are delivered to your objects. For user messages sent to script components, the engine simply calls a special Defold Lua function named `on_message()`. You can send arbitrary messages to any existing object or component and it is up to the code on the recipient side to respond to the message. If you send a message to a script component and the script code ignores the message, that is fine. The responsibility of dealing with messages is fully on the receiving end. The engine will check the message target address. If you try sending a message to an unknown recipient, Defold will signal an error in the console: ```lua -- Try to post to a non existing object msg.post("dont_exist#script", "hello") ``` ```txt ERROR:GAMEOBJECT: Instance '/dont_exists' could not be found when dispatching message 'hello' sent from main:/my_object#script ``` The complete signature of the `msg.post()` call is: `msg.post(receiver, message_id, [message])` receiver : The id of the target component or game object. Note that if you target a game object, the message will be broadcast to all components in the game object. message_id : A string or hashed string with the name of the message. [message] : An optional Lua table with message data key-value pairs. Almost any type of data can be included in the message Lua table. You can pass numbers, strings, booleans, URLs, hashes and nested tables. You can not pass functions. ```lua -- Send table data containing a nested table local inventory_table = { sword = true, shield = true, bow = true, arrows = 9 } local stats = { score = 100, stars = 2, health = 4, inventory = inventory_table } msg.post("other_object#script", "set_stats", stats) ``` There is a hard limit to the `message` parameter table size. This limit is set to 2 kilobytes. There is currently no trivial way to figure out the exact memory size a table consumes but you can use `collectgarbage("count")` before and after inserting the table to monitor memory use. ### Shorthands Defold provides two handy shorthands that you can use to send messages without specifying a complete URL: `.` : Shorthand resolving to the current game object. `#` : Shorthand resolving to the current component. For example: ```lua -- Let this game object acquire input focus msg.post(".", "acquire_input_focus") ``` ```lua -- Post "reset" to the current script msg.post("#", "reset") ``` ## Receiving messages Receiving messages is a matter of making sure the target script component contains a function named `on_message()`. The function accepts four parameters: `function on_message(self, message_id, message, sender)` `self` : A reference to the script component itself. `message_id` : Contains the name of the message. The name is _hashed_. `message` : Contains the message data. This is a Lua table. If there is no data, the table is empty. `sender` : Contains the full URL of the sender. ```lua function on_message(self, message_id, message, sender) print(message_id) --> hash: [my_message_name] pprint(message) --> { --> score = 100, --> value = "some string" --> } print(sender) --> url: [main:/my_object#script] end ``` ## Messaging between game worlds If you use a collection proxy component to load a new game world into the runtime, you will want to pass messages between the game worlds. Suppose that you have loaded a collection via proxy and that the collection has its *Name* property set to "level": As soon as the collection has been loaded, initiated and enabled, you can post messages to any component or object in the new world by specifying the game world name in the recipient address "socket" field: ```lua -- Send a message to the player in the new game world msg.post("level:/player#controller", "wake_up") ``` A more in depth description on how proxies work can be found in the [Collection Proxies](#manuals:collection-proxy) documentation. ## Message chains When a message that has been posted is eventually dispatched, the recipients’ `on_message()` is called. It is quite common that the reaction code posts new messages, which are added to the message queue. When the engine starts dispatching it will work through the message queue and call each message recipient's `on_message()` function and go on until the message queue is empty. If the dispatching pass adds new messages to the queue, it will do another pass. There is, however, a hard limit to how many times the engine tries to empty the queue, which effectively puts a limit to how long message chains you can expect to be fully dispatched within a frame. You can easily test how many dispatch passes the engine performs between each `update()` with the following script: ```lua function init(self) -- We’re starting a long message chain during object init -- and keeps it running through a number of update() steps. print("INIT") msg.post("#", "msg") self.updates = 0 self.count = 0 end function update(self, dt) if self.updates < 5 then self.updates = self.updates + 1 print("UPDATE " .. self.updates) print(self.count .. " dispatch passes before this update.") self.count = 0 end end function on_message(self, message_id, message, sender) if message_id == hash("msg") then self.count = self.count + 1 msg.post("#", "msg") end end ``` Running this script will print something like the following: ```txt DEBUG:SCRIPT: INIT INFO:ENGINE: Defold Engine 1.2.36 (5b5af21) DEBUG:SCRIPT: UPDATE 1 DEBUG:SCRIPT: 10 dispatch passes before this update. DEBUG:SCRIPT: UPDATE 2 DEBUG:SCRIPT: 75 dispatch passes before this update. DEBUG:SCRIPT: UPDATE 3 DEBUG:SCRIPT: 75 dispatch passes before this update. DEBUG:SCRIPT: UPDATE 4 DEBUG:SCRIPT: 75 dispatch passes before this update. DEBUG:SCRIPT: UPDATE 5 DEBUG:SCRIPT: 75 dispatch passes before this update. ``` We see that this particular Defold engine version performs 10 dispatch passes on the message queue between `init()` and the first call to `update()`. It then performs 75 passes during each subsequent update loop. # Application lifecycle {#manuals:application-lifecycle} The lifecycle of a Defold application or game is, on the large scale, simple. The engine moves through three stages of execution: initialization, the update loop (where apps and games spend most of their time), and finalization. The manual is regarding Defold versions from 1.12.0. In version 1.12.0 changes regarding lifecycle and new `late_update()` function were introduced. In many cases only a rudimentary understanding of Defold’s inner workings is necessary. However, you might run into edge cases where the exact order Defold carries out its tasks becomes vital. This document describes how the engine runs an application from start to finish. The application starts by initializing everything needed to run the engine. It loads the main collection and calls [`init()`](https://defold.com/ref/go#init) on all loaded components that have an `init()` Lua function (script components and GUI components with GUI scripts). This allows you to do custom initialization. The application then enters the update loop where the application will spend the majority of its lifetime. Each frame, game objects and the components they contain are updated. Any script and GUI script [`update()`](https://defold.com/ref/go#update) functions are called. During the update loop messages are dispatched to their recipients, sounds are played and all graphics are rendered. At some point, the application’s lifecycle will come to an end. Before the application quits the engine steps out of the update loop and enters a finalization stage. It prepares all loaded game objects for deletion. All object components’ [`final()`](https://defold.com/ref/go#final) functions are called, which allows for custom cleanup. Then the objects are deleted and the main collection is unloaded. The steps involved in the ["dispatch messages"](#dispatching-messages) pass are shown in a separate diagram at the end of this manual for clarity and are marked in diagrams with a small "envelope with an arrow" icon 📩. ## Initialization This is where your game starts and is the first step of the running game. It can be separated into 3 phases: ### Preinitialization During `Preinitialization` phase, the engine takes many steps, before the main (bootstrap) collection is loaded. The memory profiler, sockets, graphics, HID (input devices), sound, physics and much more are set up. The application configuration (*game.project*) is also loaded and set up. The first user-controllable entry point, at the end of engine initialization, is the call to the current render script’s `init()` function. The main collection is then loaded and initialized. ### Collection Init During the `Collection Init` phase, all game objects in the collection apply their transforms: translation (change of position), rotation and scaling, to their children. All components’ `init()` functions that exist are then called. The order in which game object component `init()` functions are called is unspecified. You should not assume that the engine initializes objects belonging to the same collection in a certain order. ### Post Update in Initialization The engine then performs a full `Post Update` pass - the same pass that is performed after each `Update Loop` step later on. It is performed at the end of initialization, because your `init()` code can post new messages, instruct factories to spawn new objects, mark objects for deletion, and perform other actions. This pass carries out message delivery, actual factory game object spawning, and object deletion. Note that the `Post Update` pass includes a "dispatch messages" sequence that not only delivers queued messages, but also processes messages sent to collection proxies. Any subsequent proxy updates (enable, disable, init, final, loading, and mark for unloading) are performed during those steps. It is entirely possible to load a [collection proxy](#manuals:collection-proxy) during `init()`, ensure all its contained objects are initialized, and then unload the collection through the proxy - all this before the first component `update()` is called, i.e. before the engine has left the initialization stage and entered the update loop: ```lua function init(self) print("init()") msg.post("#collectionproxy", "load") end function update(self, dt) -- The proxy collection is unloaded before this code is reached. print("update()") end function on_message(self, message_id, message, sender) if message_id == hash("proxy_loaded") then print("proxy_loaded. Init, enable and then unload.") msg.post("#collectionproxy", "init") msg.post("#collectionproxy", "enable") msg.post("#collectionproxy", "unload") -- The proxy collection objects’ init() and final() functions -- are called before we reach this object’s update() end end ``` ## Update Loop The Update Loop runs through a specific sequence once per frame. This sequence can be defined by 5 main phases: 1. Input (processing and handling) 2. Update (including Fixed, Regular, Late and engine components’ updates) 3. Render Update 4. Post Update (unloading collection proxies, spawning and deleting game objects) 5. Frame Render (final graphics are rendered) ### Input Phase Input is read from available devices, mapped against [input bindings](#manuals:input) and then dispatched. Any game object that has acquired input focus gets input sent to all its components’ `on_input()` functions. A game object with a script component and a GUI component with a GUI script will get input to both components’ `on_input()` functions - given that they are defined and that they have acquired input focus. Any game object that has acquired input focus and contains collection proxy components dispatches input to components inside the proxy collection. This process continues recursively down enabled collection proxies within enabled collection proxies. ### Update Phase The `Update` phase is a part of the Update Loop. It is started once for the root collection, and then runs recursively for each enabled collection proxy. Within a collection, Defold processes callbacks by component type: it iterates over all instances of a component type that implements the relevant stage, calls the Lua callback for each instance, flushes messages, then moves on to the next component type. The high-level order of *script* component Lua callback stages is: 1. `fixed_update()` - called 0..N times per frame (if using fixed timestep) 2. `update()` - called 1 time per frame 3. `late_update()` - called 1 time per frame Each game object component in the main collection is traversed. If any of these components has a script with a `fixed_update()`/`update()`/`late_update()` function, then that will be called. If the component is a collection proxy, each component in the proxy collection is recursively updated with all the steps in the `Update` phase. The order in which game object component `update()` functions are called is unspecified. You should not assume that the engine updates objects belonging to the same collection in a certain order. The same is true for `fixed_update()` and `late_update()` (since 1.12.0). #### Physics For collision object components, physics messages (collisions, triggers, ray cast responses etc.) are dispatched throughout the encompassing game object to all components that contain a script with the `on_message()` function. If a [fixed timestep](#manuals:physics) is used for physics simulation, there may also be a call to the `fixed_update()` function in all script components. This function is useful in physics based games when you wish to manipulate physics objects at regular intervals to achieve a stable physics simulation. #### Transforms Before **each** component-type update, multiple times during the `Update Loop`, if needed, the transforms are updated, applying any game object movement, rotation and scaling to each game object component and any child game object components. There is one additional final transforms update at the end of the `Update Loop`, if needed. #### Engine Update Phase (no fixed updates) The tables below describe the *engine-level* update passes. They deliberately omit the exact internal component priority order (which is an engine implementation detail), but they reflect the ordering guarantees relevant to scripting: - `fixed_update()` runs before `update()` - `late_update()` runs after `update()` - posted messages are flushed between component-type updates, and also between the script callback stages When `Use Fixed Timestep` is `false` and/or Fixed Update Frequency is `0`, at the beginning of the phase it prepares `dt` and then the flow is as presented in the table below: :::sidenote Note that after **each** component type’s update, all messages are dispatched - this is not marked in the table below to keep it clean. :::’ | Step | Engine Phase | Lua Callback | Comment | |-|-|-|-| | 1 | **Update** | `update()` | Called once per frame for each component type that implements Update in the internal priority order. Additionally GO property animations started with `go.animate()` are updated here as a separate component type. **Physics** components are updated here. For each enabled Collection Proxy the whole `Update` phase is called recursively from step 1. | | 2 | **Late Update** | `late_update()` | Called once per frame for each component type that implements Late Update in the internal priority order. | | 3 | **Transforms** | | One additional final transforms update is performed at the end for each component if needed. | #### Engine Update Phase with Fixed Timestep When `Use Fixed Timestep` is `true` and Fixed Update Frequency is non-zero, at the beginning of the phase it prepares `dt` (delta time), `fixed_dt` and `num_fixed_steps` (`0..N`) - so how many times fixed update will be called, determined by the time since last update to ensure there is a fixed amount of updates. :::sidenote Note that after **each** component type’s update, all messages are dispatched - this is not marked in the table below to keep it clean. :::’ Then it loops: | Step | Engine Phase | Lua Callback | Comment | |-|-|-|-| | 1 | **Fixed Update** | `fixed_update()` | Called `0..N` times per frame depending on timing for each component type that implements Fixed Update in the internal priority order. It includes *Physics* components Fixed Update steps. | | 2 | **Update** | `update()` | Called once per frame for each component type that implements Update in the internal priority order. Additionally GO property animations started with `go.animate()` are updated here as a separate component type. For each enabled Collection Proxy the `Update` phase is called recursively from step 1. | | 3 | **Late Update** | `late_update()` | Called once per frame for each component type that implements Late Update in the internal priority order. | | 4 | **Transforms** | | One additional final transforms update is performed at the end for each component if needed. | If you ever need more details on how Defold works internally during the Update phase, it is worth reading the [`gameobject.cpp`](https://github.com/defold/defold/blob/dev/engine/gameobject/src/gameobject/gameobject.cpp) code itself. ### Render Update Phase The render update block dispatches first all messages sent to the `@render` socket (e.g. camera component `set_view_projection` messages, `set_clear_color` messages etc). The render script `update()` is then called. ### Post update Phase After the updates, a post update sequence is run. It unloads from memory collection proxies that are marked for unloading (this happens during the "dispatch messages" sequence). Any game object that is marked for deletion will call all of its component’s `final()` functions, if there are any. The code in the `final()` functions often posts new messages to the queue, so the "dispatch messages" pass is run afterwards. Any factory component that has been told to spawn a game object will do that next. Finally, game objects that are marked for deletion are actually deleted. ### Render Phase The last step in the update loop involves dispatching `@system` messages (`exit`, `reboot` messages, toggling the profiler, starting and stopping video capture, etc.). Then graphics are rendered, as is any rendering of the visual profiler (see the [Debugging documentation](#manuals:debugging)). After the graphics rendering, a video capture is done. #### Frame rate and collection time step The number of frame updates per second (which equals the number of update-loop runs per second) can be set in the project settings, or programmatically by sending a `set_update_frequency` message to the `@system` socket. In addition, it is possible to set the _time step_ for collection proxies individually by sending a `set_time_step` message to the proxy. Changing a collection’s time step does not affect the frame rate. It does affect the physics update time step as well as the `dt` variable passed to `update().` Also note that altering the time step does not alter the number of times `update()` will be called each frame --- it is always exactly once. (See the [Collection proxy manual](#manuals:collection-proxy) and [`set_time_step`](https://defold.com/ref/collectionproxy#set-time-step) for details) #### Engine throttling Defold 1.12.0 introduced an engine throttling API that can skip engine updates and rendering entirely, while still detecting input. Any input wakes up the engine again, and the engine can re-enter throttling after a cooldown. See `sys.set_engine_throttle()` API for details and usage examples. ## Finalization When the application exits, first it finishes the last update loop sequence, which will unload any collection proxies: finalizing and deleting all game objects in each proxy collection. When that is done the engine enters a finalization sequence that handles the main collection and its objects: Component `final()` functions are called first. A subsequent dispatching of messages follows. Finally, all game objects are deleted and the main collection is unloaded. The engine then proceeds with behind-the-scenes shutting down of subsystems: project configuration is deleted, the memory profiler is shut down, and so forth. The application is now completely shut down. ## Dispatching Messages **Dispatching Messages** is a special pass that is performed after **each** component type’s update, so e.g. sprites update, scripts update, and any other action that may send messages. During its execution all posted messages that are gathered in a queue are dispatched. Those are marked in the diagrams with small "envelope with an arrow" icons 📩. After all **user messages** are dispatched by calling `on_message()` for each component, Defold special messages are handled in the following order (as presented in the diagram too), for each collection proxy: 1. `load` messages - to load collection proxies marked for loading, posts back `proxy_loaded` message. 2. `unload` messages - to unload collection proxies marked for unloading, posts back `proxy_unloaded` message. 3. `init` messages - triggers the `Collection Init` phase for all collection proxies to be initialized. 4. `final` messages - triggers `final()` on all components of the proxy marked to be finalized. 5. `enable` messages - enables the collection proxy, so the `Update Loop` will be performed for it in the next frame; this implicitly triggers `init()` for each component of the collection. 6. `disable` messages - disables the collection proxy, so the `Update Loop` will **not** be performed for it in the next frame; it stops running `Update Loop` for it completely. Since any receiver components’ `on_message()` code can post additional messages, the message dispatcher will continue to dispatch posted messaged recursively until the message queue is empty. There is, however, a limit to how many runs through the message queue the message dispatcher performs. See [Message Chains](#manuals:message-passing) for details. # Importing and editing assets {#manuals:importing-assets} A game project usually consists of a large number of external assets that are produced in various specialized programs for producing graphics, 3D models, sound files, animations and so forth. Defold is built for a workflow where you work in your external tools and then import the assets into Defold as they are finalized. ## Importing assets Defold needs all the assets used in your project to be located somewhere in the project hierarchy. You therefore need to import all assets before you can use them. To import assets, simply drag the files from the file system on your computer and drop them in an appropriate place in the Defold editor *Assets pane*. Defold supports images in the PNG and JPEG image formats. PNG images must be in 32 bit RGBA format. Other image formats need to be converted before they can be used. ## Using assets When the assets are imported into Defold they can be used by the various component types supported by Defold: * Images can be used to create many kinds of visual components frequently used in 2D games. Read more about [how to import and use 2D graphics here](#manuals:importing-graphics). * Sounds can be used by the [Sound component](#manuals:sound) to play sounds. * Fonts are used by the [Label component](#manuals:label) and by [text nodes](#manuals:gui-text) in a GUI. * glTF models can be used by the [Model component](#manuals:model) to show 3D models with animations. Read more about [how to import and use 3D models here](#manuals:importing-models). ## Editing external assets Defold does not provide editing tools for images, sound files, models or animations. Such assets need to be created outside of Defold in specialized tools and imported into Defold. Defold automatically detects changes to any asset among your project files and updates the editor view accordingly. ## Editing Defold assets The editor saves all Defold assets in text based files that are merge friendly. They are also easy to create and modify with simple scripts. See [this forum thread](https://forum.defold.com/t/deftree-a-python-module-for-editing-defold-files/15210) for more information. Note though that we do not publish our file format details since they do change once in a while. You can also use [Editor Scripts](#manuals:editor-scripts) to hook into certain life-cycle events in the Editor to run scripts to generate or modify assets. Extra care should be taken when working with Defold asset files through a text editor or external tool. If you introduce errors those can prevent the file from opening in the Defold editor. Some external tools such as [Tiled](https://defold.com/assets/tiled/) and [Tilesetter](https://www.tilesetter.org/beta) can be used to generate Defold Assets automatically. # Caching assets {#manuals:caching-assets} Games created with Defold usually build in a matter of seconds, but as a project grows so does the amount of assets. Compiling fonts and compressing textures can take a significant amount of time in a large project and the asset cache exists to speed up builds by only rebuilding assets that have changed while using already compiled assets from the cache for assets that hasn't changed. Defold uses a three-tiered cache: 1. Project cache 2. Local cache 3. Remote cache ## Project cache Defold will by default cache compiled assets in the `build/default` folder of a Defold project. The project cache will speed up subsequent builds as it is only modified assets that have to be recompiled, while assets with no changes will be used from the project cache. This cache is always enabled and it used by both the editor and the command line tools. The project cache can be deleted manually by deleting the files in `build/default` or by issuing the `clean` command from the [command line build tool Bob](#manuals:bob). ## Local cache Added in Defold 1.2.187 The local cache is an optional second cache where compiled assets are stored in an external file location on the same machine or on a network drive. Thanks to its external location the contents of the cache survives a cleanup of the project cache. It can also be shared by multiple developers working on the same project. The cache is currently only available when building using the command line tools. It is enabled through the `resource-cache-local` option: ```sh java -jar bob.jar --resource-cache-local /Users/john.doe/defold_local_cache ``` Compiled assets are accessed from the local cache based on a computed checksum which takes into account the Defold engine version, the names and the contents of the source assets as well as project build options. This will guarantee that cached assets are unique and that the cache can be shared between multiple versions of Defold. Files stored in the local cache are stored indefinitely. It is up to the developer to manually remove old/unused files. ## Remote cache Added in Defold 1.2.187 The remote cache is an optional third cache where compiled assets are stored on a server and accessed through HTTP request. The cache is currently only available when building using the command line tools. It is enabled through the `resource-cache-remote` option: ```sh java -jar bob.jar --resource-cache-remote http://192.168.0.100/ ``` As with the local cache all assets are accessed from the remote cache based on a computed checksum. Cached assets are accessed through the HTTP request methods GET, PUT and HEAD. Defold does not provide the remote cache server. It is up to each developer to set this up. An example of [a basic Python server can be seen here](https://github.com/britzl/httpserver-python). # Importing 2D graphics {#manuals:importing-graphics} Defold supports many kinds of visual components frequently used in 2D games. You can use Defold to create static and animated sprites, UI components, particle effects, tile maps and bitmap fonts. Before you can create any of these visual components you need to import image files with the graphics that you wish to use. To import image files you simply drag the files from the file system on your computer and drop them in an appropriate place in the Defold editor *Assets pane*. Defold supports images in the PNG and JPEG image formats. Other image formats need to be converted before they can be used. ## Creating Defold assets When the images are imported into Defold they can be used to create Defold specific assets: Atlas : An atlas contains a list of separate images files, which are automatically combined into a larger texture image. Atlases can contain still images and *Animation Groups*, sets of images that together form a flipbook animation. Learn more about the atlas resource in the [Atlas manual](#manuals:atlas). Tile Source : A tile source references an image file that is already made out to consist of smaller sub-images ordered on a uniform grid. Another term commonly used for this type of compound image is _sprite sheet_. Tile sources can contain flipbook animations, defined by the first and last tile for the animation. It is also possible to use an image to automatically attach collision shapes to tiles. Learn more about the tile source resource in the [Tile source manual](#manuals:tilesource). Bitmap Font : A bitmap font has its glyphs in a PNG font sheet. These types of fonts provide no performance improvement from fonts generated from TrueType or OpenType font files, but can include arbitrary graphics, coloring and shadows right in the image. Learn more about bitmap fonts in the [Fonts manual](#manuals:font). ## Using Defold assets When you have converted the images into Atlas and Tile Source files you can use these to create several different kinds of visual components: : A sprite is either a static image or flipbook animation that is displayed on screen. Learn more about sprites in the [Sprite manual](#manuals:sprite). Tile map : A tilemap component pieces together a map from tiles (image and collision shapes) that come from a tile source. Tile maps cannot use atlas sources. Learn more about tilemaps in the [Tilemap manual](#manuals:tilemap). Particle fx : Particles that are spawned from a particle emitter consist of a still image or a flipbook animation from an atlas or tile source. Learn more about particle effects in the [Particle fx manual](#manuals:particlefx). GUI : GUI box nodes and pie nodes can use still images and flipbook animations from atlases and tile sources. Learn more about GUIs in the [GUI manual](#manuals:gui). # Importing 3D models {#manuals:importing-models} Defold currently support models, skeletons and animations in GL Transmission Format *.glTF* format. You can use tools such as Maya, 3D Max, Sketchup and Blender to create and/or convert 3D models into glTF format. Blender is a powerful and popular 3D modeling, animation and rendering program. It runs on Windows, macOS and Linux and is freely available for download at http://www.blender.org ## Importing to Defold To import the model, simply drag and drop the *.gltf* file or *.dae* file and the corresponding texture image into the *Assets Pane* somewhere. ## Using a model Once you have the model imported into Defold you can use it in a [Model component](#manuals:model). ## Exporting to glTF The exported *.gltf* file contain all the vertices, edges and faces that make up the model, as well as _UV coordinates_ (what part of the texture image maps to a certain part of the mesh) if you have defined them, the bones in the skeleton and animation data. * A detailed description on polygon meshes can be found on http://en.wikipedia.org/wiki/Polygon_mesh. * UV coordinates and UV mapping is described at http://en.wikipedia.org/wiki/UV_mapping. Defold imposes some limitations on exported animation data: * Defold currently only supports baked animations. Animations need to have matrices for each animated bone each keyframe, and not position, rotation and scale as separate keys. * Animations are also linearly interpolated. If you do more advanced curve interpolation the animations needs to be prebaked from the exporter. ### Requirements When you export a model it's good to know that we don't yet support all features. Currently known issues/not supported features from the glTF format: * Morph target animations * Material properties * Embedded textures While our ambition is to fully support the glTF format, we're not fully there yet. If a feature is missing, please make a feature request for it in [our repo](https://github.com/defold/defold/issues) ### Exporting a texture If you do not already have a texture for your model you can use Blender to generate a texture. You should do this before you remove extra materials from the model. Start by selecting the mesh and all of its vertices: When all vertices are selected you unwrap the mesh to get the UV layout: You can then proceed to export the UV layout to an image that can be used as a texture: ### Exporting using Blender You export your model using the Export menu option. Select the model before you select the Export menu option and check "Selection Only" to only export the model. # Introduction {#manuals:adapting-graphics-to-screen-size} There are several things to consider when adapting your game and graphics to different screen sizes: * Is this a retro game with low resolution pixel perfect graphics or a modern game with HD quality graphics? * How should the game behave when played in full screen on different screen sizes? * Should the player see more of the game content on a high resolution screen or should the graphics adaptively zoom to always show the same content? * How should the game deal with aspect ratios other than the one you have set in *game.project*? * Should the player see more of the game content? Or maybe there should be black bars? Or maybe resized GUI elements? * What kind of menus and on-screen gui components do you need and how should they adapt to different screen sizes and screen orientations? * Should menus and other gui components change layout when the orientation changes or should they keep the same layout regardless of orientation? This manual will address some of these things and suggest best practices. ## How to change how your content is rendered The Defold render script give you total control over the entire rendering pipeline. The render script decides the order as well as what and how to draw things. The default behavior of the render script is to always draw the same area of pixels, defined by the width and height in the *game.project* file, regardless if the window is resized or the actual screen resolution doesn't match. This will result in the content being stretched if the aspect ratio changes and zoomed in or out if the window size changes. In some games this might be acceptable, but it is more likely that you want to show more or less game content if the screen resolution or aspect ratio is different, or at least make sure to zoom the content without changing the aspect ratio. The default stretch behavior can easily be changed and you can read more about how to do this in the [Render manual](#manuals:render). ## Retro/8-bit graphics Retro/8-bit graphics often refer to games emulating the graphical style of old game consoles or computers with their low resolution and limited color palette. As an example the Nintendo Entertainment System (NES) had a screen resolution of 256x240, the Commodore 64 had 320x200 and the Gameboy had 160x144, all of which are only a fraction of the size of modern screens. In order to make games emulating this graphical style and screen resolution playable on a modern high resolution screen the graphics has to be upscaled or zoomed several times. One simple way of doing this is to draw all of your graphics in the low resolution and style that you wish to emulate and zoom the graphics when it is rendered. This can easily be achieved in Defold using the render script and the [Fixed Projection](#manuals:render) set to a suitable zoom value. Let's take this tileset and player character ([source](https://ansimuz.itch.io/grotto-escape-game-art-pack)) and use them for an 8-bit retro game with a resolution of 320x200: Setting 320x200 in the *game.project* file and launching the game would look like this: The window is absolutely tiny on a modern high resolution screen! Increasing the window size four times to 1280x800 makes it more suitable for a modern screen: Now that the window size is more reasonable we also need to do something about the graphics. It's so small it's very hard to see what is going on in the game. We can use the render script to set a fixed and zoomed projection: ```Lua msg.post("@render:", "use_fixed_projection", { zoom = 4 }) ``` The same result can be achieved by attaching a [Camera component](#manuals:camera) to a game object and check *Orthographic Projection* and set *Orthographic Zoom* to 4.0: This will give the following result: This is better. The window and graphics both have a good size, but if we look closer there is an obvious problem: The graphics look blurred! This is caused by the way the zoomed in graphics is sampled from the texture when rendered by the GPU. The default setting in the *game.project* file under the Graphics section is *linear*: Changing this to *nearest* will give the result we are after: Now we have crisp pixel-perfect graphics for our retro game. There are even more things to consider, such as disabling sub-pixels for sprites in *game.project*: When the Subpixels option is disabled sprites will never get rendered on half pixels and instead always snap to the nearest full pixel. ## High resolution graphics When dealing with high resolution graphics we need to approach project and content setup in a different way than for retro/8-bit graphics. With bitmap graphics you need to create your content in such a way that it looks good on a high resolution screen when shown at a 1:1 scale. Just like for retro/8-bit graphics you need to change the render script. In this case you want the graphics to scale with the screen size while maintaining the original aspect ratio: ```Lua msg.post("@render:", "use_fixed_fit_projection") ``` This will make sure that the screen will resize to always show the same amount of content as specified in the *game.project* file, possibly with additional content shown above and below or to the sides, depending on if the aspect ratio differs or not. You should configure the width and height in the *game.project* file to a size that allows you to show your game content unscaled. ### High DPI setting and retina screens If you also wish to support high resolution retina screens you can enable this in the *game.project* file in the Display section: This will create a high dpi back buffer on displays that support it. The game will render in double the resolution than what is set in the Width and Height settings, which will still be the logical resolution used in scripts and properties. This means that all measurements stay the same and any content that is rendered at 1x scale will look the same. But if you import high res images and scale them to 0.5x they will be high dpi on screen. ## Creating an adaptive GUI The system for creating GUI components is built around a number of basic building blocks, or [nodes](#manuals:gui), and while it may seem overly simple it can be used to create anything from buttons to complex menus and popups. The GUIs that you create can be configured to automatically adapt to screen size and orientation changes. You can for instance keep nodes anchored to the top, bottom or sides of the screen and nodes can either keep their size or stretch. The relationship between nodes as well as their size and appearance can also be configured to change when the screen size or orientation changes. ### Node properties Each node in a gui has a pivot point, a horizontal and vertical anchor as well as an adjust mode. * The pivot point defines the center point of a node. * The anchor mode controls how the node’s vertical and horizontal position is altered when the scene boundaries, or the parent node’s boundaries are stretched to fit the physical screen size. * The adjust mode setting controls what happens to a node when the scene boundaries, or the parent node’s boundaries, are adjusted to fit the physical screen size. You can learn more about these properties [in the GUI manual](#manuals:gui). ### Layouts Defold supports GUIs that automatically adapt to screen orientation changes on mobile devices. By using this feature you can design a GUI that can adapt to the orientation and aspect ratio of a range of screen sizes. It is also possible to create layouts that match particular device models. You can learn more about this system in the [GUI Layouts manual](#manuals:gui-layouts) ## Testing different screen sizes The Debug menu contains an option to simulate the resolution of either a certain device model resolution or a custom resolution. While the application is running you can select `Debug->Simulate Resolution` and pick one of the device models from the list. The running application window will resize and you'll be able to see how your game looks in a different resolution or with a different aspect ratio. # Live update {#manuals:live-update} When bundling a game, Defold packs all the game resources into the resulting platform specific package. In most cases this is preferred since the running engine has instant access to all resources and can load them swiftly from storage. However, there are instances where you might want to postpone the loading of resources to a later stage. For instance: - Your game features a series of episodes and you wish to include only the first one for players to try out before they decide if they want to continue with the rest of the game. - Your game is targeted for HTML5. On the browser, loading an application from storage means that the entire application package has to be downloaded before startup. On such a platform you may wish to send a minimal start package and get the app up and running quickly before you download the rest of the game resources. - Your game contains very large resources (images, videos etc) that you wish to postpone the downloading of until they are about to show in the game. This is to keep the install size down. The Live update functionality expands the concept of the collection proxy with a mechanism allowing the runtime to fetch and store resources to the application bundle that were intentionally left out of the bundle at build time. It allows you to have your content split up into multiple archives: * _Base Archive_ * Level Common Files * Level Pack 1 * Level Pack 2 * ... ## Preparing content for Live update Suppose we are making a game containing large, high resolution image resources. The game keeps these images in collections with a game object and a sprite with the image: To have the engine load such a collection dynamically, we can simply add a collection proxy component and point it to *`monalisa.collection`*. Now the game can choose when to load the content in the collection from storage into memory by sending a `load` message to the collection proxy. However, we want to go further and control the loading of the resources contained in the collection ourselves. This is done by simply checking the *Exclude* checkbox in the collection proxy properties, telling Defold to leave any content in *`monalisa.collection`* out when creating an application bundle. Any resources referenced by the base game package, will not be excluded. ## Live update settings When Defold creates an application bundle it needs to store any excluded resources somewhere. The project settings for Live update govern the location for those resources. The settings are found under `Project ▸ Live update Settings...`. This will create a settings file if none exists. In *game.project*, select which live-update settings file to use when bundling. This allows for using different live-update settings for different environments, for example live, QA, development etc. There are currently three ways that Defold can store the resources. Choose the method in the *Mode* dropdown in the settings window: `Zip` : This option tells Defold to create a Zip archive file with any excluded resources. The archive is saved at the location specified in the *Export path* setting. `Folder` : This option tells Defold to create a folder with all the excluded resources. It works exactly the same way as Zip, but uses a directory instead of an archive. This may be useful in cases where you need to post-process files before uploading and plan to pack them into an archive yourself. `Amazon` : This option tells Defold to automatically upload excluded resources to an Amazon Web Service (AWS) S3 bucket. Fill in your AWS *Credential profile* name, select the appropriate *Bucket* and provide a *Prefix* name. You can read more on how to setup an AWS account in this [aws guide](#manuals:live-update-aws) ## Bundling with Live update Building and running from the editor (`Project ▸ Build`) does not support Live Update. In order to test Live Update you need to bundle the project. To bundle with Live update is easy. Select `Project ▸ Bundle ▸ ...` and then the platform you want to create an application bundle for. This opens the bundling dialog: When bundling, any excluded resource will be left out of the application bundle. By checking the *Publish Live update content* checkbox, you tell Defold to either upload the excluded resources to Amazon or to create a Zip archive, depending on how you have set up your Live update settings (see above). The published Live Update content still includes `liveupdate.game.dmanifest`, which contains the full resource list needed for remote delivery. When publishing archive-based Live Update content, *Strip Live Update Entries from Main Manifest* (`liveupdate.exclude_entries_from_main_manifest`) is enabled by default. With this setting enabled, Live Update-only resources are removed from the bundled `game.dmanifest`, which reduces bundle size and runtime memory usage. Disable it only if you need the deprecated behavior where excluded entries remain in the bundled `game.dmanifest`. With the default setting enabled, `collectionproxy.get_resources()` returns `{}` until the relevant archive has been mounted. After mounting, it returns the resource hashes for that proxy. Click *Package* and select a location for the application bundle. Now you can start the application and check that everything works as expected. ## The .zip archives A live update .zip file contains files that were excluded from the base game package. While our current pipeline only supports creating a single .zip file, it is in fact possible to split that zip file into smaller .zip files. This allows for smaller downloads for a game: level packs, seasonal content etc. Each .zip file also contains a manifest file that describes the meta data for each resource contained within the .zip file. ## Splitting .zip archives It is often desirable to split the excluded content into several smaller archives for more granular control over resource usage. One such example is to split a level based game into multiple level packs. Another is to put different holiday themed UI decorations into separate archives and load and mount only the theme currently active in the calendar. The resource graph is stored in `build/default/game.graph.json` and it is automatically generated each time the project is bundled. The generated file contains a list of all resources in the project and the dependencies of each resource. Example entry: ```json { "path" : "/game/player.goc", "hexDigest" : "caa342ec99794de45b63735b203e83ba60d7e5a1", "children" : [ "/game/ship.spritec", "/game/player.scriptc" ] } ``` Each entry has a `path` which represents the unique path of the resource within the project. The `hexDigest` represents the cryptographic fingerprint of the resource and it will be the filename used in the liveupdate .zip archive. Finally the `children` field is a list of other dependencies which this resource depends on. In the example above the `/game/player.goc` has a dependency to a sprite and a script component. You can parse the `game.graph.json` file and use this information to identify groups of entries in the resource graph and store their corresponding resources in separate archives along with the original manifest file (the manifest file will be pruned at runtime so that it contains only the files in the archive). ## Live Update on Android It is possible to use Play Asset Delivery to download and mount Live Update content. Learn more [in the official manual](https://defold.com/extension-pad/). ## Content verification One of the major features of the live update system, is that you can now use many content archives, potentially from many different Defold versions. The `liveupdate.add_mount()` default behavior, is to add an engine version check when attaching a mount. This means that both the game base archive and live update archive(s) need to be created at the same time with the same engine version, using the bundle option. This will invalidate any previously downloaded archives by the client, forcing them to re-download the content. This behavior can be turned off with an options flag. When turned off, the content verification responsibility lies entirely with the developer, to guarantee that each live update archive will work with the running engine. We recommend storing some metadata for each mount, so that _directly upon startup_, the developer can decide if the mount/archive should be removed. One way to do so is to add an extra file to the zip archive after the game has been bundled. For instance by inserting a `metadata.json` with any relevant information that the game requires. Then, at startup, the game can retrieve with `sys.load_resource("/metadata.json")`. _Note that you will need a unique name for each mount's custom data, or the mounts will give you the file with the topmost priority_ Failure to do so, you may end up in a situation where the content is not compatible with the engine at all, forcing it to quit. ## Mounts The live update system can use multiple content archives at the same time. Each archive is "mounted" to the engine's resource system, with a name and priority. If two archives have the same file `sprite.texturec`, the engine will load the file from the mount with the highest priority. The engine doesn't keep a reference to any resource in a mount. Once a resource is loaded into memory, the archive may be unmounted. The resource will remain in memory until it is unloaded. The mounts are automatically re-added upon engine restart. Mounting an archive doesn't copy or move the archive. The engine only stores the path to the archive. Thus, the developer can remove the archive at any time, and the mount will also be removed at next startup. ## Scripting with Live Update To actually use the live update content, you need to download and mount the data to your game. Read more about about how to [script with live update here](#manuals:live-update-scripting). The legacy single-resource Live Update flow is deprecated. Avoid `collectionproxy.missing_resources()`, the deprecated manifest APIs (`liveupdate.get_current_manifest()`, `liveupdate.store_resource()`, `liveupdate.store_manifest()`, `liveupdate.store_archive()`, `liveupdate.is_using_liveupdate_data()`), and the old `resource.*` helper aliases (`resource.get_current_manifest()`, `resource.store_resource()`, `resource.store_manifest()`, `resource.store_archive()`, `resource.is_using_liveupdate_data()`) in new projects. Current projects should publish archives, mount them with `liveupdate.add_mount()`, manage them with `liveupdate.get_mounts()` and `liveupdate.remove_mount()`, and use `collectionproxy.get_resources()` when they need to inspect excluded content for a proxy. Legacy manifest-signing keys are no longer part of this pipeline: `liveupdate.settings` `publickey` and `privatekey` are deprecated and unused, and `game.public.der` is no longer generated or bundled. ## Development caveats Debugging : When running a bundled version of your game, you don't have direct access to a console. This causes problems for debugging. However, you can run the application from the command line or by double clicking the executable in the bundle directly: Now the game starts with a shell window that will output any `print()` statements: Forcing re-download of resources : The developer can download the content to any file/folder they wish, but often they're located under the application path. The location of the application support folder depends on the operating system. It can be found with `print(sys.get_save_file("", ""))`. The file liveupdate.mounts is located under the "local storage", and it's path is output to the console at start "INFO:LIVEUPDATE: Live update folder located at: ..." # Atlas {#manuals:atlas} While single images are often used as source for sprites, for performance reasons, images need to be combined into larger sets of images, called atlases. Combining sets of smaller images into atlases is especially important on mobile devices where memory and processing power is more scarce than on desktop machines or dedicated game consoles. In Defold, an atlas resource is a list of separate images files, which are automatically combined into a larger image. ## Creating an Atlas Select `New... ▸ Atlas` from the context menu in the *Assets* browser. Name the new atlas file. The editor will now open the file in the atlas editor. The atlas properties are shown in the *Properties* pane so you can edit them (see below for details). You need to populate an atlas with images or animations before you can use it as a graphics source for object components like Sprites and ParticleFX components. Make sure that you have added your images to the project (drag and drop image files to the right location in the *Assets* browser) Adding single images : Drag and drop images from the *Asset* pane to the editor view. Alternatively, `Right click` the root Atlas entry in the *Outline* pane. Select `Add Images` from the pop up context menu to add single images. A dialog opens from which you can find and select the images you want to add to the Atlas. Note that you can filter the image files and select multiple files at once. The added images are listed in the *Outline* and the full atlas can be seen in the center editor view. You may need to press `F` (`View ▸ Frame Selection` from the menu) to frame the selection. Adding flipbook animations : `Right click` the root Atlas entry in the *Outline* pane. Select `Add Animation Group` from the pop up context menu to create a flipbook animation group. A new, empty, animation group with a default name ("New Animation") is added to the atlas. Drag and drop images from the *Asset* pane to the editor view to add them to the currently selected group. Alternatively, `Right click` the new group and select `Add Images` from the context menu. A dialog opens from which you can find and select the images you want to add to the animation group. Press `Space` with the animation group selected to preview it, and `Ctrl/Cmd+T` to close the preview. Adjust the *Properties* for the animation as needed (see below). You can reorder the images in the Outline by selecting them and pressing `Alt + Up/down`. You can also easily create duplicates by copying and pasting images in the outline (From the `Edit` menu, the right click context menu or keyboard shortcuts). ## Atlas properties Each atlas resource has a set of properties. These are shown in the *Properties* pane when you select the root item in the *Outline* view. Size : Shows the computed total size of the resulting texture resource. The width and height are set to the closest power of two. Note that if you enable texture compression, some formats require square textures. Non square textures will then be resized and filled with empty space to make the texture square. See the [Texture profiles manual](#manuals:texture-profiles) for details. Margin : The number of pixels that should be added between each image. Inner Padding : The number of empty pixels that should be padded around each image. Extrude Borders : The number of edge pixels that should be repeatedly padded around each image. When the fragment shader samples pixels at the edge of an image, pixels of a neighbor image (on the same atlas texture) may bleed over. Extruding the border solves this problem. Max Page Size : The maximum size of a page in a multi-page atlas. This can be used to split an atlas into multiple pages of the same atlas to restrict atlas size while still only using a single draw call. This feature must be used in combination with multi-page atlas enabled materials found in `/builtins/materials/*_paged_atlas.material`. Rename Patterns : A comma (´,´) separated list of search-and-replace patterns, where each pattern is of the form `search=replace`. Each image's original name (the file base name) will be transformed using these patterns. (E.g. a pattern of `hat=cat,_normal=`, will rename an image of name `hat_normal` to `cat`). This is useful when matching animations between atlases. Here are examples of the different property settings with four square images of size 64x64 added to an atlas. Notice how the atlas jumps to 256x256 as soon as the images won't fit 128x128, resulting in much wasted texture space. ## Image properties Each image in an atlas has a set of properties: Id : The id of the image (read-only). Size : The width and height of the image (read-only). Pivot : The pivot point of the image (in units). Top left is (0,0) and bottom right is (1,1). Default is (0.5, 0.5). The pivot may be outside of the 0-1 range. The pivot point is where the image will be centered when used in e.g. a sprite. You can modify the pivot point by dragging the pivot handle on the editor view. The handle will be visible, only when a single image is selected. Snapping can be enabled on `Shift` down while dragging. Sprite Trim Mode : How the sprite is rendered. The default is to render the sprite as a rectangle (Sprite Trim Mode set to Off). If the sprite contains a lot of transparent pixels it may be more efficient to render the sprite as a non rectangular shape using between 4 and 8 vertices. Note that sprite trimming does not work together with slice-9 sprites. Image : Path to the image itself. ## Animation properties In addition to the list of images that are part of an animation group, a set of properties are available: Id : The name of the animation. Fps : The playback speed of the animation, expressed in frames per second (FPS). Flip horizontal : Flips the animation horizontally. Flip vertical : Flips the animation vertically. Playback : Specifies how the animation should play: - `None` does not play back at all, the first image is displayed. - `Once Forward` plays the animation one time from the first to the last image. - `Once Backward` plays the animation one time from the last to the first image. - `Once Ping Pong` plays the animation one time from the first to the last image and then back to the first image. - `Loop Forward` plays the animation repeatedly from the first to the last image. - `Loop Backward` plays the animation repeatedly from the last to the first image. - `Loop Ping Pong` plays the animation repeatedly from the first to the last image and then back to the first image. ## Runtime Texture and Atlas creation Starting from Defold 1.4.2 it is possible to create a texture and an atlas at runtime. ### Creating a Texture resource at runtime Use [`resource.create_texture(path, params)`](https://defold.com/ref/stable/resource/#resource.create_texture:path-table) to create a new texture resource: ```lua local params = { width = 128, height = 128, type = resource.TEXTURE_TYPE_2D, format = resource.TEXTURE_FORMAT_RGBA, } local my_texture_id = resource.create_texture("/my_custom_texture.texturec", params) ``` Once the texture has been created you can use [`resource.set_texture(path, params, buffer)`](https://defold.com/ref/stable/resource/#resource.set_texture:path-table-buffer) to set the pixels of the texture: ```lua local width = 128 local height = 128 local buf = buffer.create(width * height, { { name=hash("rgba"), type=buffer.VALUE_TYPE_UINT8, count=4 } } ) local stream = buffer.get_stream(buf, hash("rgba")) for y=1, height do for x=1, width do local index = (y-1) * width * 4 + (x-1) * 4 + 1 stream[index + 0] = 0xff stream[index + 1] = 0x80 stream[index + 2] = 0x10 stream[index + 3] = 0xFF end end local params = { width=width, height=height, x=0, y=0, type=resource.TEXTURE_TYPE_2D, format=resource.TEXTURE_FORMAT_RGBA, num_mip_maps=1 } resource.set_texture(my_texture_id, params, buf) ``` It is possible to use `resource.set_texture()` to also update a sub-region of the texture by using a buffer width and height less than the full size of the texture and by changing the x and y parameters to `resource.set_texture()`. The texture can be used directly on a [model component](#manuals:model) using `go.set()`: ```lua go.set("#model", "texture0", my_texture_id) ``` ### Creating an Atlas at runtime If the texture should be used on a [sprite component](#manuals:sprite) it first needs to be used by an atlas. Use [`resource.create_atlas(path, params)`](https://defold.com/ref/stable/resource/#resource.create_atlas:path-table) to create an Atlas: ```lua local params = { texture = texture_id, animations = { { id = "my_animation", width = width, height = height, frame_start = 1, frame_end = 2, } }, geometries = { { vertices = { 0, 0, 0, height, width, height, width, 0 }, uvs = { 0, 0, 0, height, width, height, width, 0 }, indices = {0,1,2,0,2,3} } } } local my_atlas_id = resource.create_atlas("/my_atlas.texturesetc", params) -- assign the atlas to the 'sprite' component on the same go go.set("#sprite", "image", my_atlas_id) -- play the "animation" sprite.play_flipbook("#sprite", "my_animation") ``` # Buffer {#manuals:buffer} The Buffer resource is used to describe one or more streams of values, for instance positions or colours. Each stream has a name, data type, count and the data itself. Example: ``` [ { "name": "position", "type": "float32", "count": 3, "data": [ -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, ... ] } ] ``` The above example describes a stream of positions in three dimensions, represented as 32-bit floating point numbers. The format of a Buffer file is JSON, with file extension `.buffer`. Buffer resources are typically created using external tools or scripts, for instance when exporting from modeling tools such as Blender. A Buffer resource can be used as input to a [Mesh component](#manuals:mesh). Buffer resources can also be created at runtime using the `buffer.create()` and [related API functions](https://defold.com/ref/stable/buffer/#buffer.create:element_count-declaration). # Font files {#manuals:font} Fonts are used to render text on Label components and GUI text nodes. Defold supports several font file formats: - TrueType - OpenType - BMFont Fonts added to your project are automatically converted into a texture format that Defold can render. Two font rendering techniques are available, each with its own specific benefits and drawbacks: - Bitmap - Distance field ## Offline or Runtime fonts By default, the conversion to rasterized glyph images happens at build time (offline). This has the drawback that each font needs to rasterize all possible glyphs in the build stage, producing potentially very large textures that consume memory and also increase the bundle size. By using "runtime fonts", the .ttf fonts will be bundled as-is, and the rasterization will happen on-demand at runtime. This minimizes both runtime memory usage and the bundle size. ## Text layout support (e.g. Right-to-left) The runtime fonts also have the benefit of supporting full text layout, e.g. right-to-left. We currently use the libraries [HarfBuzz](https://github.com/harfbuzz/harfbuzz), [SheenBidi](https://github.com/Tehreer/SheenBidi), [libunibreak](https://github.com/adah1972/libunibreak) and [SkriBidi](https://github.com/memononen/Skribidi). See [Enabling Runtime Fonts](#manuals:font#enabling-runtime-fonts) ## Font collection The `.fontc` file format is also known as a font collection. In offline mode, only one font is associated with it. When using runtime fonts, you can associate more than one font file (.ttf) with the font collection. This allows for using the a font collection when rendering multiple texts in different languages, while also keeping the memory footprint low. E.g. loading a collection with the Japanese font, then associate that font with the current main font, followed by unloading the Japanese font collection. ## Creating a font To create a font for use in Defold, create a new Font file by selecting `File ▸ New...` from the menu, then select `Font`. You can also `right click` a location in the *Assets* browser and select `New... ▸ Font`. Give the new font file a name and click `Ok`. The new font file now opens in the editor. Drag the font you wish to use into the *Assets* browser and drop it in a good spot. Set the *Font* property to the font file and set the font properties as needed. ## Properties *Font* : The TTF, OTF or *`.fnt`* file to use for generating the font data. *Material* : The material to use when rendering this font. Make sure to change this for distance field and BMFonts (see below for details). *Output Format* : The type of font data that is generated. - `TYPE_BITMAP` converts the imported OTF or TTF file into a font sheet texture where the bitmap data is used to render text nodes. The color channels are used to encode the face shape, outline and drop shadow. For *`.fnt`* files, the source texture bitmap is used as is. - `TYPE_DISTANCE_FIELD` The imported font is converted into a font sheet texture where the pixel data represents not screen pixels but distances to the font edge. See below for details. *Render Mode* : The render mode to use for glyph rendering. - `MODE_SINGLE_LAYER` produces a single quad for each character. - `MODE_MULTI_LAYER` produces separate quads for the glyph shape, outline and shadows respectively. The layers are rendered in back-to-front order, which prevents a character from obscuring previously rendered characters if the outline is wider than the distance between glyphs. This render mode also enables proper drop shadow offsetting, as specified by the Shadow X/Y properties in the font resource. *Size* : The target size of the glyphs in pixels. *Antialias* : If the font should be antialiased when baked onto the target bitmap. Set to 0 if you want pixel perfect font rendering. *Alpha* : The transparency of the glyph. 0.0--1.0 where 0.0 means transparent and 1.0 opaque. *Outline Alpha* : The transparency of the generated outline. 0.0--1.0. *Outline Width* : The width of the generated outline in pixels. Set to 0 for no outline. *Shadow Alpha* : The transparency of the generated shadow. 0.0--1.0. Shadow support is enabled by the built-in font material shaders and handles both the single and multi layered render mode. If you don't need layered font rendering or shadow support, it is best to use a simpler shader such as the *`builtins/font-singlelayer.fp`*. *Shadow Blur* : For bitmap fonts, this setting indicates the number of times a small blur kernel will be applied to each font glyph. For distance field fonts, this setting equals the actual pixel width of the blur. *Shadow X/Y* : The horizontal and vertical offset in pixels of the generated shadow. This setting will only affect the glyph shadow when the Render Mode is set to `MODE_MULTI_LAYER`. *Characters* : Which characters to include in the font. By default this field include the ASCII printable characters (character codes 32-126). You can add or remove characters from this field to include more or less characters in the font.. For runtime fonts, this text acts as a cache prewarming with the correct glyphs. This happens during load time. See `font.prewarm_text()`. The ASCII printable characters are: space ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ \` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ *All Chars* : If you check this property all glyphs available in the source file will be included in the output. *Cache Width/Height* : Constrains the size of the glyph cache bitmap. When the engine renders text, it looks up the glyph from the cache bitmap. If it does not exist there, it will be added to the cache before rendering. If the cache bitmap is too small to contain all the glyphs the engine is asked to render, an error is signalled (`ERROR:RENDER: Out of available cache cells! Consider increasing cache_width or cache_height for the font.`). If set to 0 the cache size is set automatically, and will grow to 2048x4096 max. ## Distance field fonts Distance field fonts store the distance to the edge of the glyph in the texture instead of bitmap data. When the engine renders the font, a special shader is required to interpret the distance data and use that to draw the glyph. Distance field fonts are more resource intensive than bitmap fonts, but allow for greater sizing flexibility. Make sure to change the *Material* property of the font to *`builtins/fonts/font-df.material`* (or any other material that can handle the distance field data) when you create the font---or the font will not use the correct shader when it is rendered to screen. ## Bitmap BMFonts In addition to generated bitmaps Defold supports prebaked bitmap "BMFont" format fonts. These fonts consists of a PNG font sheet with all the glyphs. In addition, a *`.fnt`* file contains information on where on the sheet each glyph can be found as well as size and kerning information. (Note that Defold does not support the XML version of the *`.fnt`* format that is used by Phaser and some other tools) These types of fonts provide no performance improvement from bitmap fonts generated from TrueType or OpenType font files, but can include arbitrary graphics, coloring and shadows right in the image. Add the generated *`.fnt`* and *`.png`* files to your Defold project. These files should reside in the same folder. Create a new font file and set the *font* property to the *`.fnt`* file. Make sure that *output_format* is set to `TYPE_BITMAP`. Defold will not generate a bitmap but use the one provided in the PNG. To create a BMFont, you need to use a tool that can generate the appropriate files. Several options exist: * [Bitmap Font Generator](http://www.angelcode.com/products/bmfont/), a Windows only tool provided by AngelCode. * [Shoebox](http://renderhjs.net/shoebox/), a free Adobe Air based app for Windows and macOS. * [Hiero](https://libgdx.com/wiki/tools/hiero), an open source Java based tool. * [Glyph Designer](https://71squared.com/glyphdesigner), a commercial macOS tool from 71 Squared. * [bmGlyph](https://www.bmglyph.com), a commercial macOS tool from Sovapps. For the font to render correctly, don't forget to set the material property to *`builtins/fonts/font-fnt.material`* when you create the font. ## Artifacts and best practices Generally, bitmap fonts are best when the font is rendered with no scaling. They are faster to render to screen than distance field fonts. Distance field fonts respond very good to upscaling. Bitmap fonts, on the other hand, being just pixelated images will increase in size so the pixels will grow as the font is scaled, resulting in blocky artifacts. The following is a sample at font size 48 pixels, scaled up 4 times. When scaling down, bitmap textures can be nicely and efficiently scaled down and antialiased by the GPU. A bitmap font keeps its color better than a distance field font. Here is a zoom of the same sample font at size 48 pixels, scaled down to 1/5 of the size: Distance field fonts need to be rendered to a target size that is big enough to hold distance information that can express the curves of the font glyphs. This is the same font as above, but at 18 pixels size and scaled up 10 times. It is clear that this is too small to encode the shapes of this typeface: If you don't want shadow or outline support, set their respective alpha values to zero. Otherwise, shadow and outline data will still be generated, taking up unnecessary memory. ## Font Cache A font resource in Defold will result in two things at runtime, a texture and the font data. * The font data consist of a list of glyph entries, each containing some basic kerning info and the bitmap data for that glyph. * The texture is internally called the "glyph cache texture" and it will be used when rendering text for a specific font. At runtime, when rendering text, the engine will first loop through the glyphs to be rendered to check which glyphs are available in the texture cache. Each glyph that is missing from the glyph texture cache will trigger a texture upload from the bitmap data stored in the font data. Each glyph is placed internally in the cache according to the font baseline, which enables calculating local texture coordinates of the glyph within its corresponding cache cell in a shader. This means that you can achieve certain text effects such as gradients or texture overlays dynamically. The engine exposes metrics about the cache to the shader via a special shader constant called `texture_size_recip`, which contains the following information in the vector components: * `texture_size_recip.x` is the inverse of the cache width * `texture_size_recip.y` is the inverse of the cache height * `texture_size_recip.z` is the ratio of cache cell width to the cache width * `texture_size_recip.w` is the ratio of cache cell height to the cache height For example - to generate a gradient in a shader fragment, simply write: `float horizontal_gradient = fract(var_texcoord0.y / texture_size_recip.w);` For more information about shader uniforms, see the [Shader manual](#manuals:shader). ## Enabling Runtime Fonts It is possible to use runtime generation for SDF type fonts, when using TrueType (.ttf) fonts. This approach can greatly reduce the download size and runtime memory consumption of a Defold game. The small downside is the asynchronous nature of generating each glyph. * Enable the feature by setting `font.runtime_generation` in game.project. * Add an [App Manifest](#manuals:app-manifest) and enable the `Use full text layout system` option. This builds a custom engine that has this feature enabled. This feature is currently experimental, but with the intention to be used as the default workflow in the future. The `font.runtime_generation` setting affects all .ttf fonts in the project. ### Font Scripting #### Prewarming glyph cache In order to make the runtime fonts easier to use, they support prewarming of the glyph cache. This means the font will generate the glyphs listed in *Characters* in the font. If `All Chars` is selected, there will be no prewarming as it defeats the purpose of not having to generate all glyphs at the same time. If the `Characters` field of the `.fontc` file is set, this is used as a text, to figure out which glyphs needs to be updated in the glyph cache. It is also possible to manually update the glyph cache by calling `font.prewarm_text(font_collection, text, callback)`. It provides a callback to let you know when all the missing glyphs have been added to the glyph cache, and it's safe to present the text on screen. ### Adding/removing fonts to a font collection For runtime fonts, it's possible to add or remove fonts (.ttf) to a font collection. This is useful when a large font has been split up into multiple files for different character sets (e.g. CJK) Adding a font to a font collection doesn't automatically load or render all the glyphs. ```lua -- get the main font local font_collection = go.get("#label", "font") font.add_font(font_collection, self.language_ttf_hash) -- get the selected language font local font_collection_language = go.get("localization_japanese#label", "font") local font_info = font.get_info(font_collection_language) self.language_ttf_hash = font_info.fonts[1].path_hash -- get the first font (the one specified in the editor) font.add_font(self.font_collection, self.language_ttf_hash) -- increases the reference count to the font ``` ```lua -- remove the font reference font.add_font(self.font_collection, self.language_ttf_hash) ``` ### Prewarming glyphs To properly show a text with a runtime font, the glyphs need to be resolved. The `font.prewarm_text()` does this for you. It is an asynchronous operation, and once it's done and you get the callback, it's safe to progress to show any message containing the glyphs. If the glyph cache gets full, the oldest glyph in the cache will be evicted. ```lua font.prewarm_text(self.font_collection, info.text, function (self, request_id, result, err) if result then print("PREWARMING OK!") label.set_text(self.label, info.text) else print("Error prewarming text:", err) end end) ``` # Resource management {#manuals:resource} If you make a very small game, the limitations of the target platform (memory footprint, bundle size, computing power and battery consumption) may not ever pose any problems. However, when making larger games, and especially on handheld devices, memory consumption will likely be one of the biggest constraints. An experienced team will carefully make resource budgets against platform constraints. Defold provides a range of features to help manage memory and bundle size. This manual gives an overview to these features. ## The static resource tree When you build a game in Defold, you statically declare the resource tree. Every single part of the game is linked into the tree, starting with the bootstrap collection (usually called "main.collection"). The resource tree follows any reference and includes all resources associated with those references: - Game object and component data (atlases, sounds etc). - Factory component prototypes (game objects and collections). - Collection proxy component references (collections). - [Custom resources](#manuals:project-settings) declared in *game.project*. Defold also has a concept of [bundle resources](#manuals:project-settings). Bundle resources are included with the application bundle, but are not part of the resource tree. The bundle resources can be anything from platform specific support files to external files [loaded from the file system](#manuals:file-access) and used by your game (for instance FMOD sound banks). When the game is *bundled*, only what is in the resource tree will be included. Anything that is not referenced in the tree is left out. There is no need to manually select what to include or exclude from the bundle. When the game is *run*, the engine starts at the bootstrap root of the tree and pulls resources into memory: - Any referenced collection and its content. - Game objects and component data. - Factory component prototypes (game objects and collections). However, the engine will not automatically load the following types of referenced resources at runtime: - Game world collections referenced through collection proxies. Game worlds are relatively large so you will need to manually trigger loading and unloading of these in code. See [the Collection proxy manual](#manuals:collection-proxy) for details. - Files added via the *Custom Resources* setting in *game.project*. These files are manually loaded with the [`sys.load_resource()`](https://defold.com/ref/sys/#sys.load_resource) function. The default way Defold bundles and loads resources can be altered to give fine grained control over how and when resources enter memory. ## Dynamically loading factory resources Resources referenced by factory components are normally loaded into memory when the component is loaded. The resources are then ready for being spawned into the game as soon as the factory exists in the runtime. To change the default behavior and postpone the loading of factory resources you can simply mark a factory with the *Load Dynamically* checkbox. With this box checked, the engine will still include the referenced resources in the game bundle, but it will not automatically load the factory resources. Instead, you have two options: 1. Call [`factory.create()`](https://defold.com/ref/factory/#factory.create) or [`collectionfactory.create()`](https://defold.com/ref/collectionfactory/#collectionfactory.create) when you want to spawn objects. This will load the resources synchronously, then spawn new instances. 2. Call [`factory.load()`](https://defold.com/ref/factory/#factory.load) or [`collectionfactory.load()`](https://defold.com/ref/collectionfactory/#collectionfactory.load) to load the resources asynchronously. When the resources are ready for spawning, a callback is received. Read the [Factory manual](#manuals:factory) and the [Collection factory manual](#manuals:collection-factory) for details on how this works. ## Unloading dynamically loaded resources Defold keeps reference counters for all resources. If a resource's counter reaches zero it means that nothing refers to it anymore. The resource is then automatically unloaded from memory. For example, if you delete all objects spawned by a factory and you also delete the object holding the factory component, the resources previously referred to by the factory is unloaded from memory. For factories that are marked *Load Dynamically* you can call the [`factory.unload()`](https://defold.com/ref/factory/#factory.unload) or [`collectionfactory.unload()`](https://defold.com/ref/collectionfactory/#collectionfactory.unload) function. This call removes the factory component's reference to the resource. If nothing else refers to the resource (all spawned objects are deleted, for instance), the resource will be unloaded from memory. ## Excluding resources from bundle With collection proxies, it is possible to leave out all the resources the component refers to from the bundling process. This is useful if you need to keep the bundle size to a minimum. For instance, when running games on the web as HTML5 the browser will download the whole bundle before executing the game. By marking a collection proxy as *Exclude* the referenced resource will be left out of the game bundle. Instead, you can store excluded collections on selected cloud storage. The [Live update manual](#manuals:live-update) explains how this feature works. # Tile source {#manuals:tilesource} A *Tile Source* can be used by a [Tilemap component](#manuals:tilemap) to paint tiles onto a grid area or it can be used as the graphics source for a [Sprite](#manuals:sprite) or [Particle Effect component](#manuals:particlefx). You can also use the *Collision Shapes* from the tile source in a Tilemap for [collision detection and physics simulation](#manuals:physics) ([example](https://defold.com/examples/tilemap/collisions/)). ## Creating a tile source You need an image containing all the tiles. Each tile must have the exact same dimensions and be placed in a grid. Defold supports _spacing_ between the tiles and a _margin_ around each tile. Once you have the source image created, you can create a Tile Source: - Import the image to your project by dragging it into a project location in the *Assets* browser. - Create a new tile source file (`right click` a location in the *Assets* browser, then select `New... ▸ Tile Source`). - Name the new file. - The file now opens in the tile source editor. - Click the browse-button next to the *Image* property and select your image. Now you should see the image displayed in the editor. - Adjust the *Properties* to match the source image. When everything is correct the tiles will line up perfectly. Size : The size of the source image. Tile Width : The width of each tile. Tile Height : The height of each tile. Tile Margin : The number of pixels surrounding each tile (orange in the image above). Tile Spacing : The number of pixels between each tile (blue in the image above). Inner Padding : Specifies how many empty pixels should be automatically added around the tile in the resulting texture used when the game is run. Extrude Border : Specifies how many times the edge pixels should be automatically replicated around the tile in the resulting texture used when the game is run. Collision : Specifies the image to use to automatically generate collision shapes for tiles. ## Tile source flip-book animations To define an animation in a tile source the animation frame tiles must lie next to each other in a sequence left to right. The sequence can wrap from one row to the next. All newly created tile sources have a default animation named "`anim`". You can add new animations by `right clicking` the tile source root in the *Outline* and selecting `Add ▸ Animation`. Selecting an animation displays the animation *Properties*. Id : The identity of the animation. Must be unique for the tile source. Start Tile : The first tile of the animation. Numbering starts at 1 in the top left corner and goes to the right, line by line down to the bottom right corner. End Tile : The last tile of the animation. Playback : Specifies how the animation should play: - `None` does not play back at all, the first image is displayed. - `Once Forward` plays the animation one time from the first to the last image. - `Once Backward` plays the animation one time from the last to the first image. - `Once Ping Pong` plays the animation one time from the first to the last image and then back to the first image. - `Loop Forward` plays the animation repeatedly from the first to the last image. - `Loop Backward` plays the animation repeatedly from the last to the first image. - `Loop Ping Pong` plays the animation repeatedly from the first to the last image and then back to the first image. Fps : The playback speed of the animation, expressed in frames per second (FPS). Flip horizontal : Flips the animation horizontally. Flip vertical : Flips the animation vertically. ## Tile source collision shapes Defold uses an image specified in the *Collision* property to generate a _convex_ shape for each tile. The shape will outline the part of the tile that has color information, i.e. is not 100% transparent. Often it is sensible to use the same image for collision as the one containing the actual graphics, but you are free to specify a separate image if you want collision shapes that differ from the visuals. When you specify a collision image, the preview is updated with an outline on each tile indicating the generated collision shapes. The tile source outline lists collision groups that you have added to the tile source. New tile source files will get one "default" collision group added. You can add new groups by `right clicking` the tile source root in the *Outline* and selecting `Add ▸ Collision Group`. To select the tile shapes that should belong to a certain group, select the group in th *Outline*, then click each tile that you wish to assign to the group. The outline of the tile and shape is colored with the group's color. The color is automatically assigned to the group in the editor. To remove a tile from its collision group, select the tile source root element in the *Outline*, then click the tile. # Texture filtering and sampling {#manuals:texture-filtering} Texture filtering decides the visual result in cases when a _texel_ (a pixel in a texture) is not perfectly aligned with a screen pixel. This happens when you move a graphical element that contains the texture less than a pixel. The following filter methods are available: Nearest : The nearest texel will be picked to color the screen pixel. This sampling method should be chosen if you want a perfect one-to-one pixel mapping from your textures to what you see on screen. With nearest filtering everything will snap from pixel to pixel when moving. This may look twitchy if the Sprite moves slowly. Linear : The texel will be averaged with its neighbors before coloring the screen pixel. This produces smooth appearances for slow, continuous motions as a Sprite will bleed into the pixels before fully coloring them--thus it is possible to move a Sprite less than a whole pixel. The setting for which filtering to use is stored in the [Project Settings](#manuals:project-settings) file. There are two settings: default_texture_min_filter : Minifying filtering applies whenever the texel is smaller than the screen pixel. default_texture_mag_filter : Magnifying filtering applies whenever the texel is larger than the screen pixel. Both settings accept the values `linear`, `nearest`, `nearest_mipmap_nearest`, `nearest_mipmap_linear`, `linear_mipmap_nearest` or `linear_mipmap_linear`. For example: ```ini [graphics] default_texture_min_filter = nearest default_texture_mag_filter = nearest ``` If you don’t specify anything, both are set to `linear` by default. Note that the setting in *game.project* is used by in the default samplers. If you specify samplers in a custom material, you can set the filter method on each sampler specifically. See the [Materials manual](#manuals:material) for details. # Texture profiles {#manuals:texture-profiles} Defold supports automatic texture processing and compression of image data (in *Atlas*, *Tile sources*, *Cubemaps* and stand-alone textures used for models, GUI etc). There are two types of compression, software image compression and hardware texture compression. 1. Software compression (such as PNG and JPEG) reduces the storage size of image resources. This makes the the final bundle size smaller. However, the image files need to be uncompressed when read into memory so even though an image is small on disk, it can have a large memory footprint. 2. Hardware texture compression also reduces the storage size of image resources. But, unlike software compression, it reduces the in-memory footprint for textures. This is because the graphics hardware is able to directly manage compressed textures without first having to uncompress them. The processing of textures is configured through a specific texture profile. In this file you create _profiles_ that express what compressed format(s) and type should be used when creating bundles for a specific platform. _Profiles_ are then tied to matching file _paths patterns_, allowing fine tuned control over what files in your project should be compressed and exactly how. Since all available hardware texture compression is lossy, you will get artifacts in your texture data. These artifacts are highly dependent on how your source material looks and what compression method is used. You should test your source material and experiment to get the best results. Google is your friend here. You can select what software image compression is applied on the final texture data (compressed or raw) in the bundle archives. Defold supports [Basis Universal](https://github.com/BinomialLLC/basis_universal) and [ASTC](https://www.khronos.org/opengl/wiki/ASTC_Texture_Compression) compression formats. Compression is a resource intensive and time consuming operation that can cause _very_ long build times depending on the number of texture images to compress and also the chosen texture formats and type of software compression. ### Basis Universal Basis Universal (or BasisU for short) compresses the image into a intermediary format that is transcoded at runtime to a hardware format appropriate for the current device's GPU. The Basis Universal format is a high quality but lossy format. All images are also compressed using LZ4 for further reduction of file size when stored in the game archive. ### ASTC ASTC is a flexible and efficient texture compression format developed by ARM and standardized by the Khronos Group. It offers a wide range of block sizes and bit rates, allowing developers to balance image quality and memory usage effectively. ASTC supports various block sizes, from 4×4 to 12×12 texels, corresponding to bit rates ranging from 8 bits per texel down to 0.89 bits per texel. This flexibility enables fine-grained control over the trade-off between texture quality and storage requirements. ASTC supports various block sizes, from 4×4 to 12×12 texels, corresponding to bit rates ranging from 8 bits per texel down to 0.89 bits per texel. This flexibility enables fine-grained control over the trade-off between texture quality and storage requirements. The following table shows the supported block sizes and their corresponding bit rates: | Block Size (width x height) | Bits per pixel | | --------------------------- | -------------- | | 4x4 | 8.00 | | 5x4 | 6.40 | | 5x5 | 5.12 | | 6x5 | 4.27 | | 6x6 | 3.56 | | 8x5 | 3.20 | | 8x6 | 2.67 | | 10x5 | 2.56 | | 10x6 | 2.13 | | 8x8 | 2.00 | | 10x8 | 1.60 | | 10x10 | 1.28 | | 12x10 | 1.07 | | 12x12 | 0.89 | #### Supported devices While ASTC provides great results, it is not supported by all graphics cards. Here is a small list of supported devices based on vendor: | GPU vendor | Support | | ------------------ | --------------------------------------------------------------------- | | ARM (Mali) | All ARM Mali GPUs that support OpenGL ES 3.2 or Vulkan support ASTC. | | Qualcomm (Adreno) | Adreno GPUs supporting OpenGL ES 3.2 or Vulkan support ASTC. | | Apple | Apple GPUs since the A8 chip support ASTC. | | NVIDIA | ASTC support is mostly for mobile GPUs (e.g., Tegra-based chips). | | AMD (Radeon) | AMD GPUs that support Vulkan generally support ASTC via software. | | Intel (Integrated) | ASTC is supported in modern Intel GPUs via software. | ## Texture profiles Each project contains a specific *.texture_profiles* file that contains the configuration used when compressing textures. By default, this file is *builtins/graphics/default.texture_profiles* and it has a configuration matching every texture resource to a profile using RGBA with no hardware texture compression and using the default ZLib file compression. To add texture compression: - Select `File ▸ New...` and choose *Texture Profiles* to create a new texture profiles file. (Alternatively copy *default.texture_profiles* to a location outside of *builtins*) - Choose a name and location for the new file. - Change the *texture_profiles* entry in *game.project* to point to the new file. - Open the *.texture_profiles* file and configure it according to your requirements. You can turn on and off the use of texture profiles in the editor preferences. Select `File ▸ Preferences...`. The *General* tab contains a checkbox item *Enable texture profiles*. ## Path Settings The *Path Settings* section of the texture profiles file contains a list of path patterns and which *profile* to use when processing resources that match the path. The paths are expressed as "Ant Glob" patterns (see [documentation](http://ant.apache.org/manual/dirtasks.html#patterns) for details). Patterns can be expressed using the following wildcards: `*` : Matches zero or more characters. For instance `sprite*.png` matches the files *`sprite.png`*, *`sprite1.png`* and *`sprite_with_a_long_name.png`*. `?` : Matches exactly one character. For instance: `sprite?.png` matches the files *sprite1.png*, *`spriteA.png`* but not *`sprite.png`* or *`sprite_with_a_long_name.png`*. `**` : Matches a complete directory tree, or---when used as the name of a directory---zero or more directories. For instance: `/gui/**` matches all files in the directory */gui* and all its subdirectories. This example contains two path patterns and their corresponding profiles. `/gui/**/*.atlas` : All *.atlas* files in directory *`/gui`* or any of its subdirectories will be processed according to profile "gui_atlas". `/**/*.atlas` : All *.atlas* files anywhere in the project will be process according to the profile "atlas". Note that the more generic path is put last. The matching algorithm works top down. The first occurrence that matches the resource path will be used. A matching path expression further down the list never overrides the first match. Had the paths been put in the opposite order every atlas would have been processed with profile "atlas", even the ones in directory *`/gui`*. Texture resources that _do not_ match any path in the profiles file will be compiled and scaled to the closest power of 2, but will otherwise be left intact. ## Profiles The *profiles* section of the texture profiles file contains a list of named profiles. Each profile contains one or more *platforms*, each platform being described by a list of properties. *Platforms* : Specifies a matching platform. `OS_ID_GENERIC` matches all platforms, `OS_ID_WINDOWS` matches Windows target bundles, `OS_ID_IOS` matches iOS bundles and so on. Note that if `OS_ID_GENERIC` is specified, it will be included for all platforms. If two [path settings](#path-settings) matches the same file and the path uses different profiles with different platforms **both** profiles will be used and **two** texture will be generated. *Formats* : One or more texture formats to generate. If several formats are specified, textures for each format are generated and included in the bundle. The engine selects textures of a format that is supported by the runtime platform. *Mipmaps* : If checked, mipmaps are generated for the platform. Unchecked by default. *Premultiply alpha* : If checked, alpha is premultiplied into the texture data. Checked by default. *Max Texture Size* : If set to a non-zero value, textures are limited in pixel size to the specified number. Any texture that has a width or height larger than the specified value will be scaled down. The *Formats* added to a profile each have the following properties: *Format* : The format to use when encoding the texture. See below for all available texture formats. *Compressor* : The compressor to use when encoding the texture. *Compressor Preset* : Selects a compression preset to use for encoding the resulting compressed image. Each compressor preset is unique to the compressor and its settings depend on the compressor itself. To simplify these settings, the current compression presets come in four levels: | Preset | Note | | --------- | --------------------------------------------- | | `LOW` | Fastest compression. Low image quality | | `MEDIUM` | Default compression. Best image quality | | `HIGH` | Slowest compression. Smaller file size | | `HIGHEST` | Slow compression. Smallest file size | Note that the `uncompressed` compressor only has one preset called `uncompressed`, which means no compression will be applied to the textures. To see the list of available compressors, see [Compressors](#compressors) ## Texture formats Graphics hardware textures can be processed into uncompressed or *lossy* compressed data with various numbers of channels and bit depths. Hardware compression that is fixed means that the resulting image will be of a fixed size, regardless of the image content. This means that the quality loss during compression depends on the content of the original texture. Since Basis Universal compression transcoding is dependent on the device's GPU capabilities, the recommended formats for use with the Basis Universal compression is the generic formats like: `TEXTURE_FORMAT_RGB`, `TEXTURE_FORMAT_RGBA`, `TEXTURE_FORMAT_RGB_16BPP`, `TEXTURE_FORMAT_RGBA_16BPP`, `TEXTURE_FORMAT_LUMINANCE` and `TEXTURE_FORMAT_LUMINANCE_ALPHA`. The Basis Universal transcoder supports many output formats, like `ASTC4x4`, `BCx`, `ETC2`, `ETC1` and `PVRTC1`. The following lossy compression formats are currently supported: | Format | Compression | Details | | --------------------------------- | ----------- | -------------------------------- | | `TEXTURE_FORMAT_RGB` | none | 3 channel color. Alpha is discarded | | `TEXTURE_FORMAT_RGBA` | none | 3 channel color and full alpha. | | `TEXTURE_FORMAT_RGB_16BPP` | none | 3 channel color. 5+6+5 bits. | | `TEXTURE_FORMAT_RGBA_16BPP` | none | 3 channel color and full alpha. 4+4+4+4 bits. | | `TEXTURE_FORMAT_LUMINANCE` | none | 1 channel gray-scale, no alpha. RGB channels multiplied into one. Alpha is discarded. | | `TEXTURE_FORMAT_LUMINANCE_ALPHA` | none | 1 channel gray-scale and full alpha. RGB channels multiplied into one. | For ASTC, the number of channels will always be 4 (RGB + alpha), and the format itself defines the size of the block compression. Note that these formats are only compatible with an ASTC compressor - any other combination will produce a build error. `TEXTURE_FORMAT_RGBA_ASTC_4X4` `TEXTURE_FORMAT_RGBA_ASTC_5X4` `TEXTURE_FORMAT_RGBA_ASTC_5X5` `TEXTURE_FORMAT_RGBA_ASTC_6X5` `TEXTURE_FORMAT_RGBA_ASTC_6X6` `TEXTURE_FORMAT_RGBA_ASTC_8X5` `TEXTURE_FORMAT_RGBA_ASTC_8X6` `TEXTURE_FORMAT_RGBA_ASTC_8X8` `TEXTURE_FORMAT_RGBA_ASTC_10X5` `TEXTURE_FORMAT_RGBA_ASTC_10X6` `TEXTURE_FORMAT_RGBA_ASTC_10X8` `TEXTURE_FORMAT_RGBA_ASTC_10X10` `TEXTURE_FORMAT_RGBA_ASTC_12X10` `TEXTURE_FORMAT_RGBA_ASTC_12X12` ## Compressors The following texture compressors are supported by default. The data is uncompressed when the texture file is loaded into memory. | Name | Formats | Note | | --------------------------------- | ------------------------- | --------------------------------------------------------------------------------------------- | | `Uncompressed` | All formats | No compression will be applied. Default. | | `BasisU` | All RGB/RGBA formats | Basis Universal high quality, lossy compression. Lower quality level results in smaller size. | | `ASTC` | All ASTC formats | ASTC lossy compression. Lower quality level results in smaller size. | Defold 1.9.7 refactored the texture compressor pipeline to support installable compressors, which is the first step in enabling implementing a texture compression algorithm in an extension (such as WEBP, or something completely custom). ## Example image To better give an understanding of the output, here is an example. Note that the image quality, compression time and compression size are always dependent on the input image and may vary. Base image (1024x512): ### Compression times | Preset | Compression time | Relative time | | --------- | ---------------- | ------------- | | `LOW` | 0m0.143s | 0.5x | | `MEDIUM` | 0m0.294s | 1.0x | | `HIGH` | 0m1.764s | 6.0x | | `HIGHEST` | 0m1.109s | 3.8x | ### Signal loss The comparison is done using the `basisu` tool (measuring the PSNR) 100 dB means no signal loss (i.e. it's the same as the original image). | Preset | Signal | | --------- | ------------------------------------------------ | | `LOW` | Max: 34 Mean: 0.470 RMS: 1.088 PSNR: 47.399 dB | | `MEDIUM` | Max: 35 Mean: 0.439 RMS: 1.061 PSNR: 47.620 dB | | `HIGH` | Max: 37 Mean: 0.898 RMS: 1.606 PSNR: 44.018 dB | | `HIGHEST` | Max: 51 Mean: 1.298 RMS: 2.478 PSNR: 40.249 dB | ### Compression file sizes Original file size is 1572882 bytes. | Preset | File Sizes | Ratio | | --------- | ---------- | ------- | | `LOW` | 357225 | 22.71 % | | `MEDIUM` | 365548 | 23.24 % | | `HIGH` | 277186 | 17.62 % | | `HIGHEST` | 254380 | 16.17 % | ### Image quality Here are the resulting images (retrieved from the ASTC encoding using the `basisu` tool) `LOW` `MEDIUM` `HIGH` `HIGHEST` # Animation {#manuals:animation} Defold has built-in support for many types of animation that you can use as a source of graphics for components: * [Flip-book animation](#manuals:flipbook-animation) - Playing a series of still images in succession * [Model animation](#manuals:model-animation) - Playing 3D skinned animations * [Property animation](#manuals:property-animation) - Animate properties such as position, scale, rotation and many others Additional animation formats can be added through extensions: * [Rive animation](/extension-rive) - Playing vector based 2D skeletal animations * [Spine animation](/extension-spine) - Playing textured 2D skeletal animations # Flip-book animation {#manuals:flipbook-animation} A flipbook animation consists of a series of still images that are shown in succession. The technique is very similar to traditional cell animation (see http://en.wikipedia.org/wiki/Traditional_animation). The technique offers limitless opportunities since each frame can be manipulated individually. However, since each frame is stored in a unique image, the memory footprint can be high. The smoothness of animation is also dependent on the number of images shown each second but increasing the number of images usually also increase the amount of work. Defold flipbook animations are either stored as individual images added to an [Atlas](#manuals:atlas), or as a [Tile Source](#manuals:tilesource) with all frames laid out in a horizontal sequence. ## Playing flip-book animations Sprites and GUI box nodes can play flip-book animations and you have great control over them at runtime. Sprites : To run an animation during runtime you use the [`sprite.play_flipbook()`](https://defold.com/ref/sprite/?q=play_flipbook#sprite.play_flipbook:url-id-[complete_function]-[play_properties]) function. See below for an example. GUI box nodes : To run an animation during runtime you use the [`gui.play_flipbook()`](https://defold.com/ref/gui/?q=play_flipbook#gui.play_flipbook:node-animation-[complete_function]-[play_properties]) function. See below for an example. The playback mode once ping-pong will play the animation until the last frame and then reverse the order and play back until the **second** frame of the animation, not back to the first frame. This is done so that chaining of animations becomes easier. ### Sprite example Suppose that your game has a "dodge" feature that allows the player to press a specific button to dodge. You have created four animations to support the feature with visual feedback: "idle" : A looping animation of the player character idling. "dodge_idle" : A looping animation of the player character idling while being in the dodging stance. "start_dodge" : A play-once transition animation taking the player character from standing to dodging. "stop_dodge" : A play-once transition animation taking the player character from dodging back to standing. The following script provides the logic: ```lua local function play_idle_animation(self) if self.dodge then sprite.play_flipbook("#sprite", hash("dodge_idle")) else sprite.play_flipbook("#sprite", hash("idle")) end end function on_input(self, action_id, action) -- "dodge" is our input action if action_id == hash("dodge") then if action.pressed then sprite.play_flipbook("#sprite", hash("start_dodge"), play_idle_animation) -- remember that we are dodging self.dodge = true elseif action.released then sprite.play_flipbook("#sprite", hash("stop_dodge"), play_idle_animation) -- we are not dodging anymore self.dodge = false end end end ``` ### GUI box node example When selecting an animation or image for a node, you are in fact assigning the image source (atlas or tile source) and default animation in one go. The image source is statically set in the node, but the current animation to play can be changed in runtime. Still images are treated as one frame animations so changing an image means in run time is equivalent to playing a different flipbook animation for the node: ```lua function init(self) local character_node = gui.get_node("character") -- This requires that the node has a default animation in the same atlas or tile source as -- the new animation/image we're playing. gui.play_flipbook(character_node, "jump_left") end ``` ## Completion callbacks The `sprite.play_flipbook()` and `gui.play_flipbook()` functions support an optional Lua callback function as the last argument. This function will be called when the animation has played to the end. The function is never called for looping animations. The callback can be used to trigger events on animation completion or to chain multiple animations together. Examples: ```lua local function flipbook_done(self) msg.post("#", "jump_completed") end function init(self) sprite.play_flipbook("#character", "jump_left", flipbook_done) end ``` ```lua local function flipbook_done(self) msg.post("#", "jump_completed") end function init(self) gui.play_flipbook(gui.get_node("character"), "jump_left", flipbook_done) end ``` # 3D skinned animation {#manuals:model-animation} Skeletal animation of 3D models use the bones of the model to apply deformation to vertices in the model. For details on how to import 3D data into a Model for animation, see the [Model documentation](#manuals:model). ## Playing animations Models are animated with the [`model.play_anim()`](https://defold.com/ref/model#model.play_anim) function: ```lua function init(self) -- Start the "wiggle" animation back and forth on #model model.play_anim("#model", "wiggle", go.PLAYBACK_LOOP_PINGPONG) end ``` Defold currently supports only baked animations. Animations need to have matrices for each animated bone each keyframe, and not position, rotation and scale as separate keys. Animations are also linearly interpolated. If you do more advanced curve interpolation the animations needs to be prebaked from the exporter. ### The bone hierarchy The bones in the Model skeleton are represented internally as game objects. You can retrieve the instance id of the bone game object in runtime. The function [`model.get_go()`](https://defold.com/ref/model#model.get_go) returns the id of the game object for the specified bone. ```lua -- Get the middle bone go of our wiggler model local bone_go = model.get_go("#wiggler", "Bone_002") -- Now do something useful with the game object... ``` ### Cursor animation In addition to using the `model.play_anim()` to advance a model animation, *Model* components expose a "cursor" property that can be manipulated with `go.animate()` (more about [property animations](#manuals:property-animation)): ```lua -- Set the animation on #model but don't start it model.play_anim("#model", "wiggle", go.PLAYBACK_NONE) -- Set the cursor to the beginning of the animation go.set("#model", "cursor", 0) -- Tween the cursor between 0 and 1 pingpong with in-out quad easing. go.animate("#model", "cursor", go.PLAYBACK_LOOP_PINGPONG, 1, go.EASING_INOUTQUAD, 3) ``` ## Completion callbacks The model animation `model.play_anim()`) support an optional Lua callback function as the last argument. This function will be called when the animation has played to the end. The function is never called for looping animations, nor when an animation is manually canceled via `go.cancel_animations()`. The callback can be used to trigger events on animation completion or to chain multiple animations together. ```lua local function wiggle_done(self, message_id, message, sender) -- Done animating end function init(self) model.play_anim("#model", "wiggle", go.PLAYBACK_ONCE_FORWARD, nil, wiggle_done) end ``` ## Playback Modes Animations can be played either once or in a loop. How the animation plays is determined by the playback mode: * `go.PLAYBACK_NONE` * `go.PLAYBACK_ONCE_FORWARD` * `go.PLAYBACK_ONCE_BACKWARD` * `go.PLAYBACK_ONCE_PINGPONG` * `go.PLAYBACK_LOOP_FORWARD` * `go.PLAYBACK_LOOP_BACKWARD` * `go.PLAYBACK_LOOP_PINGPONG` # Property animation {#manuals:property-animation} All numeric properties (numbers, vector3, vector4 and quaternions) and shader constants can be animated with the built-in animation system, using the function `go.animate()`. The engine will automatically "tween" properties for you according to given playback modes and easing functions. You can also specify custom easing functions. ## Property animation To animate a game object or component property, use the function `go.animate()`. For GUI node properties, the corresponding function is `gui.animate()`. ```lua -- Set the position property y component to 200 go.set(".", "position.y", 200) -- Then animate it go.animate(".", "position.y", go.PLAYBACK_LOOP_PINGPONG, 100, go.EASING_OUTBOUNCE, 2) ``` To stop all animations of a given property, call `go.cancel_animations()`, or for GUI nodes, `gui.cancel_animation()`: ```lua -- Stop euler z rotation animation on the current game object go.cancel_animations(".", "euler.z") ``` If you cancel the animation of a composite property, like `position`, any animations of the sub-components (`position.x`, `position.y` and `position.z`) will be cancelled as well. The [Properties Manual](#manuals:properties) contains all the available properties on game objects, components and GUI nodes. ## GUI node property animation Almost all GUI node properties are possible to animate. You can, for instance, make a node invisible by setting its `color` property to full transparency and then fade it into view by animating the color to white (i.e. no tint color). ```lua local node = gui.get_node("button") local color = gui.get_color(node) -- Animate the color to white gui.animate(node, gui.PROP_COLOR, vmath.vector4(1, 1, 1, 1), gui.EASING_INOUTQUAD, 0.5) -- Animate the outline red color component gui.animate(node, "outline.x", 1, gui.EASING_INOUTQUAD, 0.5) -- And move to x position 100 gui.animate(node, hash("position.x"), 100, gui.EASING_INOUTQUAD, 0.5) ``` ## Completion callbacks The property animation functions `go.animate()` and `gui.animate()` support an optional Lua callback function as the last argument. This function will be called when the animation has played to the end. The function is never called for looping animations, nor when an animation is manually canceled via `go.cancel_animations()` or `gui.cancel_animation()`. The callback can be used to trigger events on animation completion or to chain multiple animations together. ## Easing Easing defines how the animated value changes over time. The images below describe the functions applied over time to create the easing. The following are valid easing values for `go.animate()`: |---|---| | `go.EASING_LINEAR` | | | `go.EASING_INBACK` | `go.EASING_OUTBACK` | | `go.EASING_INOUTBACK` | `go.EASING_OUTINBACK` | | `go.EASING_INBOUNCE` | `go.EASING_OUTBOUNCE` | | `go.EASING_INOUTBOUNCE` | `go.EASING_OUTINBOUNCE` | | `go.EASING_INELASTIC` | `go.EASING_OUTELASTIC` | | `go.EASING_INOUTELASTIC` | `go.EASING_OUTINELASTIC` | | `go.EASING_INSINE` | `go.EASING_OUTSINE` | | `go.EASING_INOUTSINE` | `go.EASING_OUTINSINE` | | `go.EASING_INEXPO` | `go.EASING_OUTEXPO` | | `go.EASING_INOUTEXPO` | `go.EASING_OUTINEXPO` | | `go.EASING_INCIRC` | `go.EASING_OUTCIRC` | | `go.EASING_INOUTCIRC` | `go.EASING_OUTINCIRC` | | `go.EASING_INQUAD` | `go.EASING_OUTQUAD` | | `go.EASING_INOUTQUAD` | `go.EASING_OUTINQUAD` | | `go.EASING_INCUBIC` | `go.EASING_OUTCUBIC` | | `go.EASING_INOUTCUBIC` | `go.EASING_OUTINCUBIC` | | `go.EASING_INQUART` | `go.EASING_OUTQUART` | | `go.EASING_INOUTQUART` | `go.EASING_OUTINQUART` | | `go.EASING_INQUINT` | `go.EASING_OUTQUINT` | | `go.EASING_INOUTQUINT` | `go.EASING_OUTINQUINT` | The following are valid easing values for `gui.animate()`: |---|---| | `gui.EASING_LINEAR` | | | `gui.EASING_INBACK` | `gui.EASING_OUTBACK` | | `gui.EASING_INOUTBACK` | `gui.EASING_OUTINBACK` | | `gui.EASING_INBOUNCE` | `gui.EASING_OUTBOUNCE` | | `gui.EASING_INOUTBOUNCE` | `gui.EASING_OUTINBOUNCE` | | `gui.EASING_INELASTIC` | `gui.EASING_OUTELASTIC` | | `gui.EASING_INOUTELASTIC` | `gui.EASING_OUTINELASTIC` | | `gui.EASING_INSINE` | `gui.EASING_OUTSINE` | | `gui.EASING_INOUTSINE` | `gui.EASING_OUTINSINE` | | `gui.EASING_INEXPO` | `gui.EASING_OUTEXPO` | | `gui.EASING_INOUTEXPO` | `gui.EASING_OUTINEXPO` | | `gui.EASING_INCIRC` | `gui.EASING_OUTCIRC` | | `gui.EASING_INOUTCIRC` | `gui.EASING_OUTINCIRC` | | `gui.EASING_INQUAD` | `gui.EASING_OUTQUAD` | | `gui.EASING_INOUTQUAD` | `gui.EASING_OUTINQUAD` | | `gui.EASING_INCUBIC` | `gui.EASING_OUTCUBIC` | | `gui.EASING_INOUTCUBIC` | `gui.EASING_OUTINCUBIC` | | `gui.EASING_INQUART` | `gui.EASING_OUTQUART` | | `gui.EASING_INOUTQUART` | `gui.EASING_OUTINQUART` | | `gui.EASING_INQUINT` | `gui.EASING_OUTQUINT` | | `gui.EASING_INOUTQUINT` | `gui.EASING_OUTINQUINT` | ## Custom easing You can create custom easing curves by defining a `vector` with a set of values and then provide the vector instead of one of the predefined easing constants above. The vector values express a curve from the start value (`0`) to the target value (`1`). The runtime samples values from the vector and linearly interpolates when calculating values in between the points expressed in the vector. For example, the vector: ```lua local values = { 0, 0.4, 0.2, 0.2, 0.5, 1 } local my_easing = vmath.vector(values) ``` yields the following curve: The following example causes the y position of a game object to jump between the current position and 200 according to a square curve: ```lua local values = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 } local square_easing = vmath.vector(values) go.animate("go", "position.y", go.PLAYBACK_LOOP_PINGPONG, 200, square_easing, 2.0) ``` # Components {#manuals:components} Components are used to give specific expression and/or functionality to game objects. Components have to be contained inside game objects and are affected by the position, rotation and scale of the game object that contains the component: Many components have type specific properties that can be manipulated and there are component type specific functions available for interacting with them in runtime: ```lua -- disable the can "body" sprite msg.post("can#body", "disable") -- play "hoohoo" sound on "bean" in 1 second sound.play("bean#hoohoo", { delay = 1, gain = 0.5 } ) ``` Components are either added in-place in a game object, or added to a game object as a reference to a component file: `Right-click` the game object in the *Outline* view and select `Add Component` (add in-place) or `Add Component File` (add as file reference). In most cases it makes most sense to create components in-place, but the following component types must be created in separate resource files before being added by reference to a game object: * Script * GUI * Particle FX * Tile Map ## Component types Defold supports the following component types: * [Collection factory](#manuals:collection-factory) - Spawn collections * [Collection proxy](#manuals:collection-proxy) - Load and unload collections * [Collision object](#manuals:physics) - 2D and 3D physics * [Camera](#manuals:camera) - Change the viewport and projection of the game world * [Factory](#manuals:factory) - Spawn game objects * [GUI](#manuals:gui) - Render a graphical user interface * [Label](#manuals:label) - Render a piece of text * [Mesh](#manuals:mesh) Show a 3D mesh (with run-time creation and manipulation) * [Model](#manuals:model) Show a 3D model (with optional animations) * [Particle FX](#manuals:particlefx) - Spawn particles * [Script](#manuals:script) - Add game logic * [Sound](#manuals:sound) - Play sound or music * [Sprite](#manuals:sprite) - Show a 2D image (with optional flipbook animation) * [Tilemap](#manuals:tilemap) - Show a grid of tiles Additional components can be added through extensions: * [Rive model](/extension-rive) - Render a Rive animation * [Spine model](/extension-spine) - Render a Spine animation ## Enabling and disabling components The components of a game object are enabled when the game object is created. If you wish to disable a component this is done by sending a [`disable`](https://defold.com/ref/go/#disable) message to the component: ```lua -- disable the component with id 'weapon' on the same game object as this script msg.post("#weapon", "disable") -- disable the component with id 'shield' on the 'enemy' game object msg.post("enemy#shield", "disable") -- disable all components on the current game object msg.post(".", "disable") -- disable all components on the 'enemy' game object msg.post("enemy", "disable") ``` To enable a component again you can post an [`enable`](https://defold.com/ref/go/#enable) message to the component: ```lua -- enable the component with id 'weapon' msg.post("#weapon", "enable") ``` ## Component properties The Defold components types all have different properties. The [Properties pane](#manuals:editor) in the editor will show the properties of the currently selected component in the [Outline pane](#manuals:editor). Refer to the manuals of the different component types to learn more about the available component properties. ## Component position, rotation and scale Visual components usually have a position and rotation property and most often also a scale property. These properties can be changed from the editor and in almost all cases the properties can't be changed at run-time (the only exception is sprite and label component scale which can be changed at run-time). If you need to change the position, rotation or scale of a component at run-time you instead modify the position, rotation or scale of the game object that the component belongs to. This has the side effect that all components on the game object will be affected. If you wish to only manipulate a single component out of many attached to a game object it is recommended that the component in question is moved to a separate game object and added as a child game object to the game object the component originally belonged to. ## Component draw order The draw order of visual components depend on two things: ### Render script predicates Each component is assigned a [material](#manuals:material) and each material has one or more tags. The render script will in turn define a number of predicates, each matching one or more material tags. The render script [predicates are drawn one by one](#manuals:render) in the *update()* function of the render script and the components matching the tags defined in each predicate will be drawn. The default render script will first draw sprites and tilemaps in one pass, then particle effects in another pass, both in world space. The render script will then proceed to draw GUI components in a separate pass in screen space. ### Component z-value All game objects and components are positioned in 3D space with positions expressed as vector3 objects. When you view your game's graphics content in 2D, the X and Y value determine the position of an object along the "width" and "height" axis, and the Z position determines the position along the "depth" axis. The Z position allows you to control the visibility of overlapping objects: a sprite with a Z value of 1 will appear in front of a sprite at Z position 0. By default, Defold uses a coordinate system allowing Z values between -1 and 1: The components matching a [render predicate](#manuals:render) are drawn together, and the order in which they are drawn depends on the final z-value of the component. The final z-value of a component is the sum of the z-values of the component itself, the game object it belongs to and the z-value of any parent game objects. The order in which multiple GUI components are drawn is **not** determined by the z-value of the GUI components. GUI component draw order is controlled by the [gui.set_render_order()](https://defold.com/ref/gui/#gui.set_render_order:order) function. Example: Two game objects A and B. B is a child of A. B has a sprite component. | What | Z-value | |----------|---------| | A | 2 | | B | 1 | | B#sprite | 0.5 | With the above hierarchy the final z-value of the sprite component on B is 2 + 1 + 0.5 = 3.5. If two components have the exact same z-value the order is undefined and you may end up with components flickering back and forth or components being rendered in one order on one platform and in another order on another platform. The render script defines a near and far plane for z-values. Any component with a z-value that falls outside of this range will not be rendered. The default range is -1 to 1 but [it can easily be changed](#manuals:render). The numerical precision on the Z values with a near and far limit of -1 and 1 is very high. When working with 3D assets, you may need to change the near and far limits of the default projection in a custom render script. See the [Render manual](#manuals:render) for more information. ## Component max count optimizations The *game.project* settings file contains many values specifying the maximum number of a certain resource that can exist at the same time, often counted per loaded collection (also called world). The Defold engine will use these max values to preallocate memory for this amount of memory to avoid dynamic allocations and memory fragmentation while the game is running. The Defold data structures used to represent components and other resources are optimized to use as little memory as possible but care should still be taken when setting the values to avoid allocating more memory than is actually necessary. To further optimize memory usage the Defold build process will analyse the content of the game and override the max counts if it is possible to know for certain the exact amount: * If a collection doesn't contain any factory components the exact amount of each component and Game Object will be allocated and the max count values will be ignored. * If a collection contains a factory component the spawned objects will be analysed and the max count will be used for components that can be spawned from the factories and for Game Objects. * If a collection contains a factory or a collection factory with activated "Dynamic Prototype" option, this collection will use the max counters. # Collection factories {#manuals:collection-factory} The collection factory component is used to spawn groups and hierarchies of game objects stored in collection files into a running game. Collections provide a powerful mechanism to create reusable templates, or "prefabs" in Defold. For an overview on Collections, see the [Building blocks documentation](#manuals:building-blocks#collections). Collections can be placed in the editor, or they can be dynamically inserted into your game. With a collection factory component you can spawn the contents of a collection file into a game world. This is analogous to performing factory spawning of all game objects inside the collection and then building the parent-child hierarchy between the objects. A typical use case is to spawn enemies consisting of multiple game objects (enemy + weapon, for instance). ## Spawning a collection Suppose we want a character game object and a separate shield game object childed to the character. We build the game object hierarchy in a collection file and save it as "bean.collection". The *collection proxy* component is used to create a new game world, including a separate physics world, based on a collection. The new world is accessed through a new socket. All assets contained in the collection are loaded through the proxy when you message the proxy to start loading. This makes them very useful to, for instance, change levels in a game. New game worlds come with quite a lot of overhead though so do not use them for dynamic loading of small stuff. For more information, see the [Collection proxy documentation](#manuals:collection-proxy). We then add a *Collection factory* to a gameobject that will take care of the spawning and set "bean.collection" as the component's *Prototype*: Spawning a bean and shield is now just a matter of calling the `collectionfactory.create()` function: ```lua local bean_ids = collectionfactory.create("#bean_factory") ``` The function takes 5 parameters: `url` : The id of the collection factory component that should spawn the new set of game objects. `[position]` : (optional) The world position of the spawned game objects. This should be a `vector3`. If you do not specify a position, the objects are spawned at the position of the collection factory component. `[rotation]` : (optional) The world rotation of the new game objects. This should be a `quat`. `[properties]` : (optional) A Lua table with `id`-`table` pairs used to initiate the spawned game objects. See below for how to construct this table. `[scale]` : (optional) The scale of the spawned game objects. The scale can be expressed as a `number` (greater than 0) which specifies uniform scaling along all axes. You can also provide a `vector3` where each component specifies scaling along the corresponding axis. `collectionfactory.create()` returns the identities of the spawned game objects as a table. The table keys map the hash of the collection-local id of each object to the runtime id of each object: The parent-child relationship between "bean" and "shield" is *not* reflected in the returned table. This relation only exist in the runtime scene-graph, i.e. how objects are transformed together. Re-parenting an object never changes its id. ```lua local bean_ids = collectionfactory.create("#bean_factory") go.set_scale(0.5, bean_ids[hash("/bean")]) pprint(bean_ids) -- DEBUG:SCRIPT: -- { -- hash: [/shield] = hash: [/collection0/shield], -- <1> -- hash: [/bean] = hash: [/collection0/bean], -- } ``` 1. A prefix `/collection[N]/`, where `[N]` is a counter, is added to the id to uniquely identify each instance: ## Properties When spawning a collection, you can pass property parameters to each game object by constructing a table where the keys are object ids and the values are tables with the script properties to set. ```lua local props = {} props[hash("/bean")] = { shield = false } local ids = collectionfactory.create("#bean_factory", nil, nil, props) ``` Supposing the "bean" game object in "bean.collection" defines the "shield" property. [The Script property manual](#manuals:script-properties) contains information on script properties. ```lua -- bean/controller.script go.property("shield", true) function init(self) if not self.shield then go.delete("shield") end end ``` ## Dynamic loading of factory resources By checking the *Load Dynamically* checkbox in the collection factory properties, the engine postpones the loading of the resources associated with the factory. With the box unchecked the engine loads the prototype resources when the collection factory component is loaded so they are immediately ready for spawning. With the box checked, you have two options for usage: Synchronous loading : Call [`collectionfactory.create()`](https://defold.com/ref/collectionfactory/#collectionfactory.create:url-[position]-[rotation]-[properties]-[scale]) when you want to spawn objects. This will load the resources synchronously, which may cause a hitch, then spawn new instances. ```lua function init(self) -- No factory resources are loaded when the collection factory’s -- parent collection is loaded. Calling create without -- having called load will create the resources synchronously. self.go_ids = collectionfactory.create("#collectionfactory") end function final(self) -- Delete game objects. Will decref resources. -- In this case resources are deleted since the collection -- factory component holds no reference. go.delete(self.go_ids) -- Calling unload will do nothing since factory holds -- no references collectionfactory.unload("#factory") end ``` Asynchronous loading : Call [`collectionfactory.load()`](https://defold.com/ref/collectionfactory/#collectionfactory.load:[url]-[complete_function]) to explicitly load the resources asynchronously. When the resources are ready for spawning, a callback is received. ```lua function load_complete(self, url, result) -- Loading is complete, resources are ready to spawn self.go_ids = collectionfactory.create(url) end function init(self) -- No factory resources are loaded when the collection factory’s -- parent collection is loaded. Calling load will load the resources. collectionfactory.load("#factory", load_complete) end function final(self) -- Delete game object. Will decref resources. -- In this case resources aren’t deleted since the collection factory -- component still holds a reference. go.delete(self.go_ids) -- Calling unload will decref resources held by the factory component, -- resulting in resources being destroyed. collectionfactory.unload("#factory") end ``` ## Dynamic prototype It is possible to change which *Prototype* a collection factory can create by checking the *Dynamic Prototype* checkbox in the collection factory properties. When the *Dynamic Prototype* option is checked the collection factory component can change prototype using the `collectionfactory.set_prototype()` function. Example: ```lua collectionfactory.unload("#factory") -- unload the previous resources collectionfactory.set_prototype("#factory", "/main/levels/level1.collectionc") local ids = collectionfactory.create("#factory") ``` When the *Dynamic Prototype* option is set the collection component count cannot be optimized, and the owning collection will use the default component counts from the *game.project* file. # Collection proxy {#manuals:collection-proxy} The collection proxy component is used to load and unload new game "worlds" dynamically based on the content of a collection file. They can be used to implement switching between game levels, GUI screens, loading and unloading of narrative "scenes" throughout a level, loading/unloading of mini-games and more. Defold organizes all game objects in collections. A collection can contain game objects and other collections (i.e. sub-collections). Collection proxies allow you to split your content into separate collections and then dynamically manage the loading and unloading of these collections through scripting. Collection proxies differ from [collection factory components](#manuals:collection-factory). A collection factory instantiates the contents of a collection into the current game world. Collection proxies create a new game world at runtime and thus have different use-cases. ## Creating a collection proxy component 1. Add a collection proxy component to a game object by `right-clicking` a game object and selecting `Add Component ▸ Collection Proxy` from the context menu. 2. Set the *Collection* property to reference a collection that you wish to dynamically load into the runtime at a later point. The reference is static and makes sure that all the content of the referenced collection end up in the final game. (You can exclude the content in the build and download it with code instead by checking the *Exclude* box and using the [Live update feature](#manuals:live-update).) ## Bootstrap When the Defold engine starts it loads and instantiates all game objects from a *bootstrap collection* into the runtime. It then initializes and enables the game objects and their components. Which bootstrap collection the engine should use is set in the [project settings](#manuals:project-settings). By convention this collection file is usually named "main.collection". To fit the game objects and their components the engine allocates the memory needed for the whole "game world" into which the contents of the bootstrap collection are instantiated. A separate physics world is also created for any collision objects and physics simulation. Since script components need to be able to address all objects in the game, even from outside the bootstrap world, it is given a unique name: the *Name* property that you set in the collection file: If the collection that is loaded contains collection proxy components, the collections that those refer to are *not* loaded automatically. You need to control the loading of these resources through scripts. ## Loading a collection Dynamically loading a collection via proxy is done by sending a message called `"load"` to the proxy component from a script: ```lua -- Tell the proxy "myproxy" to start loading. msg.post("#myproxy", "load") ``` The proxy component will instruct the engine to allocate space for a new world. A separate runtime physics world is also created and all the game objects in the collection "`mylevel.collection`" are instantiated. The new world gets its name from the *Name* property in the collection file, in this example it is set to "`mylevel`". The name has to be unique. If the *Name* set in the collection file is already used for a loaded world, the engine will signal a name collision error: ```txt ERROR:GAMEOBJECT: The collection 'default' could not be created since there is already a socket with the same name. WARNING:RESOURCE: Unable to create resource: build/default/mylevel.collectionc ERROR:GAMESYS: The collection /mylevel.collectionc could not be loaded. ``` When the engine has finished loading the collection, the collection proxy component will send a message named `"proxy_loaded"` back to the script that sent the `"load"` message. The script can then initialize and enable the collection as a reaction to the message: ```lua function on_message(self, message_id, message, sender) if message_id == hash("proxy_loaded") then -- New world is loaded. Init and enable it. msg.post(sender, "init") msg.post(sender, "enable") ... end end ``` `"load"` : This message tells the collection proxy component to start loading its collection into a new world. The proxy will send back a message called `"proxy_loaded"` when it's done. `"async_load"` : This message tells the collection proxy component to start background loading its collection into a new world. The proxy will send back a message called `"proxy_loaded"` when it's done. `"init"` : This message tells the collection proxy component that all the game objects and components that has been instantiated should be initialized. All script `init()` functions are called at this stage. `"enable"` : This message tells the collection proxy component that all the game objects and components should be enabled. All sprite components begin to draw when enabled, for instance. ## Addressing into the new world The *Name* set in the collection file properties is used to address game objects and components in the loaded world. If you, for instance, create a loader object in the bootstrap collection you may need to communicate with it from any loaded collection: ```lua -- tell the loader to load the next level: msg.post("main:/loader#script", "load_level", { level_id = 2 }) ``` And if you need to communicate with a game object in the loaded collection from the loader you can send a message using the [full URL to the object](#manuals:addressing): ```lua msg.post("mylevel:/myobject", "hello") ``` It is not possible to directly access game objects in a loaded collection from outside of the collection: ```lua local position = go.get_position("mylevel:/myobject") -- loader.script:42: function called can only access instances within the same collection. ``` ## Unloading a world To unload a loaded collection, you send messages corresponding to the converse steps of the loading: ```lua -- unload the level msg.post("#myproxy", "disable") msg.post("#myproxy", "final") msg.post("#myproxy", "unload") ``` `"disable"` : This message tells the collection proxy component to disable all the game object and components in the world. Sprites stop being rendered at this stage. `"final"` : This message tells the collection proxy component to finalize all the game object and components in the world. All scripts' `final()` functions are called at this stage. `"unload"` : This message tells the collection proxy to remove the world completely from memory. If you don’t need the finer grained control, you can send the `"unload"` message directly without first disabling and finalizing the collection. The proxy will then automatically disable and finalize the collection before it’s unloaded. When the collection proxy has finished unloading the collection it will send a `"proxy_unloaded"` message back to the script that sent the `"unload"` message: ```lua function on_message(self, message_id, message, sender) if message_id == hash("proxy_unloaded") then -- Ok, the world is unloaded... ... end end ``` ## Time step Collection proxy updates can be scaled by altering the _time step_. This means that even though the game ticks at a steady 60 FPS, a proxy can update at a higher or lower pace, affecting things such as: * Physics simulation speed * The `dt` passed to `update()` * [Game object and gui property animations](#manuals:animation) * [Flipbook animations](#manuals:animation) * [Particle FX simulations](#manuals:particlefx) * Timer speed You can also set the update mode, which allows you to control if the scaling should be performed discretely (which only makes sense with a scale factor below 1.0) or continuously. You control the scale factor and the scaling mode by sending the proxy a `set_time_step` message: ```lua -- update loaded world at one-fifth-speed. msg.post("#myproxy", "set_time_step", {factor = 0.2, mode = 1} ``` To see what's happening when changing the time step, we can create an object with the following code in a script component and put it in the collection we're altering the timestep of: ```lua function update(self, dt) print("update() with timestep (dt) " .. dt) end ``` With a time step of 0.2, we get the following result in the console: ```txt INFO:DLIB: SSDP started (ssdp://192.168.0.102:54967, http://0.0.0.0:62162) INFO:ENGINE: Defold Engine 1.2.37 (6b3ae27) INFO:ENGINE: Loading data from: build/default DEBUG:SCRIPT: update() with timestep (dt) 0 DEBUG:SCRIPT: update() with timestep (dt) 0 DEBUG:SCRIPT: update() with timestep (dt) 0 DEBUG:SCRIPT: update() with timestep (dt) 0 DEBUG:SCRIPT: update() with timestep (dt) 0.016666667535901 DEBUG:SCRIPT: update() with timestep (dt) 0 DEBUG:SCRIPT: update() with timestep (dt) 0 DEBUG:SCRIPT: update() with timestep (dt) 0 DEBUG:SCRIPT: update() with timestep (dt) 0 DEBUG:SCRIPT: update() with timestep (dt) 0.016666667535901 ``` `update()` is still called 60 times a second, but the value of `dt` changes. We see that only 1/5 (0.2) of the calls to `update()` will have a `dt` of 1/60 (corresponding to 60 FPS)---the rest is zero. All physics simulations will also be updated according to that `dt` and advance only in one fifth of the frames. You can use the collection time step functionality to pause your game, for instance while showing a popup or when the window has lost focus. Use `msg.post("#myproxy", "set_time_step", {factor = 0, mode = 0})` to pause and `msg.post("#myproxy", "set_time_step", {factor = 1, mode = 1})` to resume. See [`set_time_step`](https://defold.com/ref/collectionproxy#set_time_step) for more details. ## Caveats and common issues Physics : Through collection proxies it is possible to load more than one top level collection, or *game world* into the engine. When doing so, it is important to know that each top level collection is a separate physical world. Physics interactions (collisions, triggers, ray-casts) only happen between objects belonging to the same world. So even if the collision objects from two worlds visually sits right on top of each other, there cannot be any physics interaction between them. Memory : Each loaded collection creates a new game world which comes with a relatively large memory footprint. If you load dozens of collections simultaneously through proxies, you might want to reconsider your design. To spawn many instances of game object hierarchies, [collection factories](#manuals:collection-factory) are more suitable. Input : If you have objects in your loaded collection that require input actions, you need to make sure that the game object that contains the collection proxy acquires input. When the game object receives input messages these are propagated to the components of that object, i.e. the collection proxies. The input actions are sent via the proxy into the loaded collection. # Collision objects {#manuals:physics-objects} A collision object is a component you use to give a game object physical behaviour. A collision object has physical properties like weight, restitution and friction and its spatial extension is defined by one or more _shapes_ that you attach to the component. Defold supports the following types of collision objects: Static objects : Static objects never move but a dynamic object that collides with a static object will react by bouncing and/or sliding. Static objects are very useful for building level geometry (i.e. ground and walls) that does not move. They are also cheaper performance-wise than dynamic objects. You cannot move or otherwise change static objects. Dynamic objects : Dynamic objects are simulated by the physics engine. The engine solves all collisions and applies resulting forces. Dynamic objects are good for objects that should behave realistically. The most common way to affect them is indirectly, by [applying forces](https://defold.com/ref/physics/#apply_force) or changing the angular [damping](https://defold.com/ref/stable/physics/#angular_damping) and [velocity](https://defold.com/ref/stable/physics/#linear_velocity) and the linear [damping](https://defold.com/ref/stable/physics/#linear_damping) and [velocity](https://defold.com/ref/stable/physics/#angular_velocity). It is also possible to directly manipulate the position and orientation of a dynamic object when the [Allow Dynamic Transforms setting](#manuals:project-settings) is enabled in *game.project*. Kinematic objects : Kinematic objects register collisions with other physics objects, but the physics engine do not perform any automatic simulation. The job of resolving collisions, or ignoring them, is left to you ([learn more](#manuals:physics-resolving-collisions)). Kinematic objects are very good for player or script controlled objects that require fine grained control of the physical reactions, like a player character. Triggers : Triggers are objects that register simple collisions. Triggers are light weight collision objects. They are similar to [ray casts](#manuals:physics-ray-casts) in that they read the physics world as opposed to interacting with it. They are good for objects that just need to register a hit (like a bullet) or as part of game logic where you want to trigger certain actions when an object reaches a specific point. Trigger are computationally cheaper than kinematic objects and should be used in favor of those if possible. ## Adding a collision object component A collision object component has a set of *Properties* that sets its type and physics properties. It also contains one or more *Shapes* that define the whole shape of the physics object. To add a collision object component to a game object: 1. In the *Outline* view, `right click` the game object and select `Add Component ▸ Collision Object` from the context menu. This creates a new component with no shapes. 2. `Right click` the new component and select `Add Shape ▸ Box / Capsule / Sphere`. This adds a new shape to the collision object component. You can add any number of shapes to the component. You can also use a tilemap or a convex hull to define the shape of the physics object. 3. Use the move, rotate and scale tools to edit the shapes. 4. Select the component in the *Outline* and edit the collision object's *Properties*. ## Adding a collision shape A collision component can either use several primitive shapes or a single complex shape. Learn more about the various shapes and how to add them to a collision component in the [Collision Shapes manual](#manuals:physics-shapes). ## Collision object properties Id : The identity of the component. Collision Shape : This property is used for tile map geometry or convex shapes that does not use primitive shapes. See [Collision Shapes for more information](#manuals:physics-shapes). Type : The type of collision object: `Dynamic`, `Kinematic`, `Static` or `Trigger`. If you set the object to dynamic you _must_ set the *Mass* property to a non zero value. For dynamic or static objects you should also check that the *Friction* and *Restitution* values are good for your use-case. Friction : Friction makes it possible for objects to slide realistically against each other. The friction value is usually set between `0` (no friction at all---a very slippery object) and `1` (strong friction---an abrasive object). However, any positive value is valid. The friction strength is proportional to the normal force (this is called Coulomb friction). When the friction force is computed between two shapes (`A` and `B`), the friction values of both objects are combined by the geometric mean: ```math F = sqrt( F_A * F_B ) ``` This means that if one of the objects has zero friction then the contact between them will have zero friction. Restitution : The restitution value sets the "bounciness" of the object. The value is usually between 0 (inelastic collision—the object does not bounce at all) and 1 (perfectly elastic collision---the object's velocity will be exactly reflected in the bounce) Restitution values between two shapes (`A` and `B`) are combined using the following formula: ```math R = max( R_A, R_B ) ``` When a shape develops multiple contacts, restitution is simulated approximately because Box2D uses an iterative solver. Box2D also uses inelastic collisions when the collision velocity is small to prevent bounce-jitter Linear damping : Linear damping reduces the linear velocity of the body. It is different from friction, which only occurs during contact, and can be used to give objects a floating appearance, like they are moving through something thicker than air. Valid values are between 0 and 1. Box2D approximates damping for stability and performance. At small values, the damping effect is independent of the time step while at larger damping values, the damping effect varies with the time step. If you run your game with a fixed time step, this never becomes an issue. Angular damping : Angular damping works like linear damping but reduces the angular velocity of the body. Valid values are between 0 and 1. Locked rotation : Setting this property totally disables rotation on the collision object, no matter what forces are brought to it. Bullet : Setting this property enables continuous collision detection (CCD) between the collision object and other dynamic collision objects. The Bullet property is ignored if the Type is not set to `Dynamic`. Group : The name of the collision group the object should belong to. You can have 16 different groups and you name them as you see fit for your game. For example "players", "bullets", "enemies" and "world". If the *Collision Shape* is set to a tile map, this field is not used but the groups names are taken from the tile source. [Learn more about collision groups](#manuals:physics-groups). Mask : The other _groups_ this object should collide with. You can name one group or specify multiple groups in a comma separated list. If you leave the Mask field empty, the object will not collide with anything. [Learn more about collision groups](#manuals:physics-groups). Generate Collision Events : If enabled, will allow this object to send collision events Generate Contact Events : If enabled, will allow this object to send contact events Generate Trigger Events : If enabled, will allow this object to send trigger events ## Runtime properties A physics object has a number of different properties that can be read and changed using `go.get()` and `go.set()`: `angular_damping` : The angular damping value for the collision object component (`number`). [API reference](https://defold.com/ref/physics/#angular_damping). `angular_velocity` : The current angular velocity of the collision object component (`vector3`). [API reference](https://defold.com/ref/physics/#angular_velocity). `linear_damping` : The linear damping value for the collision object (`number`). [API reference](https://defold.com/ref/physics/#linear_damping). `linear_velocity` : The current linear velocity of the collision object component (`vector3`). [API reference](https://defold.com/ref/physics/#linear_velocity). `mass` : The defined physical mass of the collision object component. READ ONLY. (`number`). [API reference](https://defold.com/ref/physics/#mass). # Cameras {#manuals:camera} A camera in Defold is a component that changes the viewport and projection of the game world. The camera component defines a bare bones perspective or orthographic camera that provides a view and projection matrix to the render script. A perspective camera is typically used for 3D games where the view of the camera and the size and perspective of objects is based on a view frustum and the distance and view angle from the camera to the objects in the game. For 2D games, it is often desirable to render the scene with an orthographic projection. This means that the view of the camera is no longer dictated by a view frustum, but by a box. Orthographic projection is unrealistic in that it does not alter the size of objects based on their distance. An object 1000 units away will render at the same size as an object right in front of the camera. ## Creating a camera To create a camera, `right click` a game object and select `Add Component ▸ Camera`. You can alternatively create a component file in your project hierarchy and add the component file to the game object. The camera component has the following properties that defines the camera *frustum*: Id : The id of the component Aspect Ratio : (**Perspective camera only**) - The ratio between the frustum width and height. 1.0 means that you assume a quadratic view. 1.33 is good for a 4:3 view like 1024x768. 1.78 is good for a 16:9 view. This setting is ignored if *Auto Aspect Ratio* is set. Fov : (**Perspective camera only**) - The *vertical* camera field of view expressed in _radians_. The wider the field of view, the more the camera will see. Near Z : The Z-value of the near clipping plane. Far Z : The Z-value of the far clipping plane. Auto Aspect Ratio : (**Perspective camera only**) - Set this to let the camera automatically calculate the aspect ratio. Orthographic Projection : Set this to switch the camera to an orthographic projection (see below). Orthographic Zoom : (**Orthographic camera only**) - The zoom used for the orthographic projection (> 1 = zoom in, < 1 = zoom out). Orthographic Mode : (**Orthographic camera only**) - Controls how the orthographic camera determines zoom relative to the window size and your design resolution (the values in `game.project` → `display.width/height`). - `Fixed` (uses constant zoom): Uses the current `Orthographic Zoom` value as-is. - `Auto Fit` (contain): Automatically adjusts zoom so the full design area fits inside the window. May show extra content on sides or top/bottom. - `Auto Cover` (cover): Automatically adjusts zoom so the design area covers the entire window. May crop on sides or top/bottom. Available only when `Orthographic Projection` is enabled. ## Using the camera All cameras are automatically enabled and updated during a frame, and the lua `camera` module is available in all script contexts. Since Defold 1.8.1 there is no longer a need to explicitly enable a camera via sending an `acquire_camera_focus` message to the camera component. The old acquire and release messages are still available, but it is recommended to instead use the "enable" and "disable" messages like for any other component that you wish to enable or disable: ```lua msg.post("#camera", "disable") msg.post("#camera", "enable") ``` To list all currently available cameras, you can use camera.get_cameras(): ```lua -- Note: The render calls are only available in a render script. -- The camera.get_cameras() function can be used anywhere, -- but render.set_camera can only be used in a render script. for k,v in pairs(camera.get_cameras()) do -- the camera table contains the URLs of all cameras render.set_camera(v) -- do rendering here - anything rendered here that uses materials with -- view and projection matrices specified, will use matrices from the camera. end -- to disable a camera, pass in nil (or no arguments at all) to render.set_camera. -- after this call, all render calls will use the view and projection matrices -- that are specified on the render context (render.set_view and render.set_projection) render.set_camera() ``` The scripting `camera` module has multiple functions that can be used to manipulate the camera. Here's just a few functions that can be used, to see all of the available functions, please consult the manual at the [API docs](https://defold.com/ref/camera/)). ```lua camera.get_aspect_ratio(camera) -- get aspect ratio camera.get_far_z(camera) -- get far z camera.get_fov(camera) -- get field of view camera.get_orthographic_mode(camera) -- get orthographic mode (one of camera.ORTHO_MODE_*) camera.set_aspect_ratio(camera, ratio) -- set aspect ratio camera.set_far_z(camera, far_z) -- set far z camera.set_near_z(camera, near_z) -- set near z camera.set_orthographic_mode(camera, camera.ORTHO_MODE_AUTO_FIT) -- set orthographic mode ... And so forth ``` A camera is identified by a URL, which is the full scene path of the component, including the collection, the gameobject it belongs to and the component id. In this example, you would use the URL `/go#camera` to identify the camera component from within the same collection, and `main:/go#camera` when accessing a camera from a different collection, or the render script. ```lua -- Accessing a camera from a script in the same collection: camera.get_fov("/go#camera") -- Accessing a camera from a script in a different collection: camera.get_fov("main:/go#camera") -- Accessing a camera from the render script: render.set_camera("main:/go#camera") ``` Each frame, the camera component that currently has camera focus will send a `set_view_projection` message to the "@render" socket: ```lua -- builtins/render/default.render_script -- function on_message(self, message_id, message) if message_id == hash("set_view_projection") then self.view = message.view -- [1] self.projection = message.projection end end ``` 1. The message posted from the camera component includes a view matrix and a projection matrix. The camera component supplies the render script with either a perspective or orthographic projection matrix depending on the *Orthographic Projection* property of the camera. The projection matrix also takes into account the defined near and far clipping plane, the field of view and the aspect ratio settings of the camera. The view matrix provided by the camera defines the position and orientation of the camera. A camera with an *Orthographic Projection* will center the view on the position of the game object it is attached to, while a camera with a *Perspective Projection* will have the lower left corner of the view positioned on the game object it is attached to. ### Render script When using the default render script Defold will automatically set the last enabled camera that should be used for rendering. Before this change, a script somewhere in the project needed to explicitly send the `use_camera_projection` message to the renderer to notify it that the view and projection from camera components should be used. This is no longer necessary, but it is still possible to do so for backwards compatibility purposes. Alternatively, you can set a specific camera that should be used for rendering in a render script. This could be useful in cases where you need to control more specifically which camera should be used for rendering, for example in a multiplayer game. ```lua -- render.set_camera will automatically use the view and projection matrices -- for any rendering happening until render.set_camera() is called. render.set_camera("main:/my_go#camera") ``` To check if a camera is active or not, you can use the `get_enabled` function from the [Camera API](https://defold.com/ref/alpha/camera/#camera.get_enabled:camera): ```lua if camera.get_enabled("main:/my_go#camera") then -- camera is enabled, use it for rendering! render.set_camera("main:/my_go#camera") end ``` To use the `set_camera` function together with frustum culling, you need to pass this as an option to the function: `render.set_camera("main:/my_go#camera", {use_frustum = true})` ### Panning the camera You pan/move the camera around the game world by moving the game object the camera component is attached to. The camera component will automatically send an updated view matrix based on the current x and y axis position of the camera. ### Zooming the camera You can zoom in and out when using a perspective camera by moving the game object the camera is attached to along the z-axis. The camera component will automatically send an updated view matrix based on the current z-position of the camera. You can zoom in and out when using an orthographic camera by changing the *Orthographic Zoom* property of the camera: ```lua go.set("#camera", "orthographic_zoom", 2) ``` When using an orthographic camera you can also switch how zoom is determined using the `Orthographic Mode` setting or via script: ```lua -- get current mode (one of camera.ORTHO_MODE_FIXED, _AUTO_FIT, _AUTO_COVER) local mode = camera.get_orthographic_mode("#camera") -- switch to auto-fit (contain) to always keep the full design area visible camera.set_orthographic_mode("#camera", camera.ORTHO_MODE_AUTO_FIT) -- switch to auto-cover to ensure the design area covers the window camera.set_orthographic_mode("#camera", camera.ORTHO_MODE_AUTO_COVER) -- switch back to fixed mode to control zoom manually via orthographic_zoom camera.set_orthographic_mode("#camera", camera.ORTHO_MODE_FIXED) ``` ### Adaptive zoom The concept behind adaptive zoom is to adjust the camera zoom value when the resolution of the display change from the initial resolution set in *game.project*. Two common approaches to adaptive zoom are: 1. Max zoom - Calculate a zoom value such that the content covered by the initial resolution in *game.project* will fill and expand beyond the screen bounds, possibly hiding some content to the sides or above and below. 2. Min zoom - Calculate a zoom value such that the content covered by the initial resolution in *game.project* will be completely contained within the screen bounds, possibly showing additional content to the sides or above and below. Example: ```lua local DISPLAY_WIDTH = sys.get_config_int("display.width") local DISPLAY_HEIGHT = sys.get_config_int("display.height") function init(self) local initial_zoom = go.get("#camera", "orthographic_zoom") local display_scale = window.get_display_scale() window.set_listener(function(self, event, data) if event == window.WINDOW_EVENT_RESIZED then local window_width = data.width local window_height = data.height local design_width = DISPLAY_WIDTH / initial_zoom local design_height = DISPLAY_HEIGHT / initial_zoom -- max zoom: ensure that the initial design dimensions will fill and expand beyond the screen bounds local zoom = math.max(window_width / design_width, window_height / design_height) / display_scale -- min zoom: ensure that the initial design dimensions will shrink and be contained within the screen bounds --local zoom = math.min(window_width / design_width, window_height / design_height) / display_scale go.set("#camera", "orthographic_zoom", zoom) end end) end ``` A complete example of adaptive zoom can be seen in [this sample project](https://github.com/defold/sample-adaptive-zoom). Note: With an orthographic camera you can now achieve contain/cover behavior without custom code by setting `Orthographic Mode` to `Auto Fit` (contain) or `Auto Cover` (cover). In these modes the effective zoom is computed automatically based on window size and your design resolution. ### Following a game object You can have the camera follow a game object by setting the game object the camera component is attached to as a child of the game object to follow: An alternative way is to update the position of the game object the camera component is attached to every frame as the game object to follow moves. ### Converting mouse to world coordinates When the camera has panned, zoomed or changed it's projection from the default orthographic Stretch projection the mouse coordinates provided in the `on_input()` lifecycle function will no longer match to the world coordinates of your game objects. You need to manually account for the change in view or projection. The code to convert from mouse/screen coordinates to world coordinates looks like this: ```Lua --- Convert screen to world coordinates taking into account -- the view and projection of a specific camera -- @param camera URL of camera to use for conversion -- @param screen_x Screen x coordinate to convert -- @param screen_y Screen y coordinate to convert -- @param z optional z coordinate to pass through the conversion, defaults to 0 -- @return world_x The resulting world x coordinate of the screen coordinate -- @return world_y The resulting world y coordinate of the screen coordinate -- @return world_z The resulting world z coordinate of the screen coordinate function M.screen_to_world(camera, screen_x, screen_y, z) local projection = go.get(camera, "projection") local view = go.get(camera, "view") local w, h = window.get_size() -- https://defold.com/manuals/camera/#converting-mouse-to-world-coordinates local inv = vmath.inv(projection * view) local x = (2 * screen_x / w) - 1 local y = (2 * screen_y / h) - 1 local x1 = x * inv.m00 + y * inv.m01 + z * inv.m02 + inv.m03 local y1 = x * inv.m10 + y * inv.m11 + z * inv.m12 + inv.m13 return x1, y1, z or 0 end ``` Keep in mind that the values `action.screen_x` and `action.screen_y` from `on_input()` should be used as arguments for this function. Visit the [Examples page](https://defold.com/examples/render/screen_to_world/) to see screen to world coordinate conversion in action. There is also a [sample project](https://github.com/defold/sample-screen-to-world-coordinates/) showing how to do screen to world coordinate conversion. The [third-party camera solutions mentioned in this manual](#manuals:camera) provides functions for converting to and from screen coordinates. ## Runtime manipulation You can manipulate cameras in runtime through a number of different messages and properties (refer to the [API docs for usage](https://defold.com/ref/camera/)). A camera has a number of different properties that can be manipulated using `go.get()` and `go.set()`: `fov` : The camera field-of-view (`number`). `near_z` : The camera near Z-value (`number`). `far_z` : The camera far Z-value (`number`). `orthographic_zoom` : The orthographic camera zoom (`number`). `aspect_ratio` : The ratio between the frustum width and height. Used when calculating the projection of a perspective camera. (`number`). `view` : The calculated view matrix of the camera. READ ONLY. (`matrix4`). `projection` : The calculated projection matrix of the camera. READ ONLY. (`matrix4`). ## Third-party camera solutions There are community-made camera solutions that implement common features such as screen shake, following game objects, screen-to-world coordinate conversion and much more. They can be downloaded from the Defold asset portal: - [Orthographic camera](https://defold.com/assets/orthographic/) (2D only) by Björn Ritzl. - [Defold Rendy](https://defold.com/assets/defold-rendy/) (2D and 3D) by Klayton Kowalski. # Factory components {#manuals:factory} Factory components are used to dynamically spawn game objects from a pool of objects into a running game. When you add a factory component to a game object you specify in the *Prototype* property what game object file the factory should use as a prototype (also known as "prefabs" or "blueprints" in other engines) for all new game objects it creates. To trigger the creation of a game object, call `factory.create()`: ```lua -- factory.script local p = go.get_position() p.y = vmath.lerp(math.random(), min_y, max_y) local component = "#star_factory" factory.create(component, p) ``` `factory.create()` takes 5 parameters: `url` : The id of the factory component that should spawn a new game object. `[position]` : (optional) The world position of the new game object. This should be a `vector3`. If you do not specify a position, the game object is spawned at the position of the factory component. `[rotation]` : (optional) The world rotation of the new game object. This should be a `quat`. `[properties]` : (optional) A Lua table with any script property values to initiate the game object with. See the [Script property manual](#manuals:script-properties) for information on script properties. `[scale]` : (optional) The scale of the spawned game object. The scale can be expressed as a `number` (greater than 0) which specifies uniform scaling along all axes. You can also provide a `vector3` where each component specifies scaling along the corresponding axis. For example: ```lua -- factory.script local p = go.get_position() p.y = vmath.lerp(math.random(), min_y, max_y) local component = "#star_factory" -- Spawn with no rotation but double scale. -- Set the score of the star to 10. factory.create(component, p, nil, { score = 10 }, 2.0) -- <1> ``` 1. Sets the "score" property of the star game object. ```lua -- star.script go.property("score", 1) -- <1> local speed = -240 function update(self, dt) local p = go.get_position() p.x = p.x + speed * dt if p.x < -32 then go.delete() end go.set_position(p) end function on_message(self, message_id, message, sender) if message_id == hash("collision_response") then msg.post("main#gui", "add_score", {amount = self.score}) -- <2> go.delete() end end ``` 1. The "score" script property is defined with a default value. 2. Reference the "score" script property as a value stored in "self". Defold does not currently support non uniform scaling of collision shapes. If you provide a non uniform scale value, for instance `vmath.vector3(1.0, 2.0, 1.0)` the sprite will scale correctly but the collision shapes won't. ## Addressing of factory created objects Defold's addressing mechanism makes it possible to access every object and component in a running game. The [Addressing manual](#manuals:addressing) goes into quite a bit of detail how the system works. It is possible to use the same addressing mechanism for spawned game objects and their components. It is quite often enough to use the id of the spawned object, for instance when sending a message: ```lua local function create_hunter(target_id) local id = factory.create("#hunterfactory") msg.post(id, "hunt", { target = target_id }) return id end ``` Message passing to the game object itself instead of a specific component will in fact send the message to all components. This is usually not a problem but it's good to keep in mind if the object has a lot of components. But what if you need to access a specific component on a spawned game object, for instance to disable a collision object or change a sprite image? The solution is to construct a URL from the game object id and the id of the component. ```lua local function create_guard(unarmed) local id = factory.create("#guardfactory") if unarmed then local weapon_sprite_url = msg.url(nil, id, "weapon") msg.post(weapon_sprite_url, "disable") local body_sprite_url = msg.url(nil, id, "body") sprite.play_flipbook(body_sprite_url, hash("red_guard")) end end ``` ## Tracking spawned and parent objects When you call `factory.create()` you get back the id of the new game object, allowing you to store the id for future reference. One common use is to spawn objects and add their id's to a table so you can delete them all at a later point, for instance when resetting a level layout: ```lua -- spawner.script self.spawned_coins = {} ... -- Spawn a coin and store it in the "coins" table. local id = factory.create("#coinfactory", coin_position) table.insert(self.spawned_coins, id) ``` And then later: ```lua -- spawner.script -- Delete all spawned coins. for _, coin_id in ipairs(self.spawned_coins) do go.delete(coin_id) end -- or alternatively go.delete(self.spawned_coins) ``` It is also common that you want the spawned object to be aware of the game object that spawned it. One case would be some type of autonomous object that can be spawned only one at a time. The spawned object then needs to inform the spawner when it is deleted or inactivated so another one can be spawned: ```lua -- spawner.script -- Spawn a drone and set its parent to the url of this script component self.spawned_drone = factory.create("#dronefactory", drone_position, nil, { parent = msg.url() }) ... function on_message(self, message_id, message, sender) if message_id == hash("drone_dead") then self.spawned_drone = nil end end ``` And the spawned object's logic: ```lua -- drone.script go.property("parent", msg.url()) ... function final(self) -- I'm dead. msg.post(self.parent, "drone_dead") end ``` ## Dynamic loading of factory resources By checking the *Load Dynamically* checkbox in the factory properties, the engine postpones the loading of the resources associated with the factory. With the box unchecked the engine loads the prototype resources when the factory component is loaded so they are immediately ready for spawning. With the box checked, you have two options for usage: Synchronous loading : Call [`factory.create()`](https://defold.com/ref/factory/#factory.create) when you want to spawn objects. This will load the resources synchronously, which may cause a hitch, then spawn new instances. ```lua function init(self) -- No factory resources are loaded when the factory’s parent -- collection is loaded. Calling create without having called -- load will create the resources synchronously. self.go_id = factory.create("#factory") end function final(self) -- Delete game objects. Will decref resources. -- In this case resources are deleted since the factory component -- holds no reference. go.delete(self.go_id) -- Calling unload will do nothing since factory holds no references factory.unload("#factory") end ``` Asynchronous loading : Call [`factory.load()`](https://defold.com/ref/factory/#factory.load) to explicitly load the resources asynchronously. When the resources are ready for spawning, a callback is received. ```lua function load_complete(self, url, result) -- Loading is complete, resources are ready to spawn self.go_id = factory.create(url) end function init(self) -- No factory resources are loaded when the factory’s parent -- collection is loaded. Calling load will load the resources. factory.load("#factory", load_complete) end function final(self) -- Delete game object. Will decref resources. -- In this case resources aren’t deleted since the factory component -- still holds a reference. go.delete(self.go_id) -- Calling unload will decref resources held by the factory component, -- resulting in resources being destroyed. factory.unload("#factory") end ``` ## Dynamic prototype It is possible to change which *Prototype* a factory can create by checking the *Dynamic Prototype* checkbox in the factory properties. When the *Dynamic Prototype* option is checked the factory component can change prototype using the `factory.set_prototype()` function. Example: ```lua factory.unload("#factory") -- unload the previous resources factory.set_prototype("#factory", "/main/levels/enemyA.goc") local enemy_id = factory.create("#factory") ``` When the *Dynamic Prototype* option is set the collection component count cannot be optimized, and the owning collection will use the default component counts from the *game.project* file. ## Instance limits The project setting *max_instances* in *Collection related settings* limits the total number of game object instances that can exist in a world (the main.collection loaded at startup or any world loaded via a collection proxy). All game objects that exist in the world are counted against that limit and it does not matter if they are placed by hand in the editor or spawned in runtime through a script. If you set *max_instances* to 1024 and have 24 manually placed game objects in your main collection, you can spawn an additional 1000 game objects. As soon as you delete a game object, you are free to spawn another instance. ## Pooling of game objects It may seem like a good idea to save spawned game objects in a pool and reuse them. However, the engine is already doing object pooling under the hood so additional overhead will only slow things down. It is both faster and cleaner to delete game objects and spawn new ones. # Label {#manuals:label} A *Label* component renders a piece of text on screen, in game space. By default it is sorted and drawn with all sprite and tile graphics. The component has a set of properties that governs how the text is rendered. Defold's GUI supports text but it can be tricky to place GUI elements in the game world. Labels make this easier. ## Creating a label To create a Label component, `right click` the game object and selecting `Add Component ▸ Label`. (If you want to instantiate several labels from the same template you can alternatively make a new label component file: `right click` a folder in the *Assets* browser and select `New... ▸ Label`, then add the file as component to any game objects) Set the *Font* property to the font you want to use and make sure to set the *Material* property to a material that matches the font type: ## Label properties Apart from the properties *Id*, *Position*, *Rotation* and *Scale* the following component specific properties exist: *Text* : The text content of the label. *Size* : The size of the text bounding box. If *Line Break* is set the width specifies at what point the text should break. *Color* : The color of the text. *Outline* : The color of the outline. *Shadow* : The color of the shadow. Note that the default material has shadow rendering disabled for performance reasons. *Leading* : A scaling number for the line spacing. A value of 0 gives no line spacing. Defaults to 1. *Tracking* : A scaling number for the letter spacing. Defaults to 0. *Pivot* : The pivot of the text. Use this to change text alignment (see below). *Blend Mode* : The blend mode to use when rendering the label. *Line Break* : Text alignment follows the pivot setting and setting the this property allows the text to flow over several lines. The width of the component determines where the text will wrap. Note that there has to be a space in the text for it to break. *Font* : The font resource to use for this label. *Material* : The material to use for rendering this label. Make sure to select a material that is created for the font type that you use (bitmap, distance field or BMFont). ### Blend modes The *Blend Mode* property defines how the component graphics should be blended with the graphics behind it. These are the available blend modes and how they are calculated: Alpha : Normal blending: `src.a * src.rgb + (1 - src.a) * dst.rgb` Add : Brighten the background with the color values of the corresponding pixels of the component: `src.rgb + dst.rgb` Multiply : Darken the background with values of the corresponding pixels of the component: `src.rgb * dst.rgb` Screen : Opposite of Multiply. Brighten background and values of the corresponding pixels of the component: `src.rgb - dst.rgb * dst.rgb` ### Pivot and alignment By setting the *Pivot* property you can change the alignment mode for the text. *Center* : If the pivot is set to `Center`, `North` or `South`, the text is center-aligned. *Left* : If the pivot is set to any of the `West` modes, the text is left-aligned. *Right* : If the pivot is set to any of the `East` modes, the text is right-aligned. ## Runtime manipulation You can manipulate labels in runtime by getting and setting the label text as well as the various other properties. `color` : The label color (`vector4`) `outline` : The label outline color (`vector4`) `shadow` : The label shadow color (`vector4`) `scale` : The label scale, either a `number` for uniform scaling or a `vector3` for individual scaling along each axis. `size` : The label size (`vector3`) ```lua function init(self) -- Set the text of the "my_label" component in the same game object -- as this script. label.set_text("#my_label", "New text") end ``` ```lua function init(self) -- Set the color of the "my_label" component in the same game object -- as this script. Color is a RGBA value stored in a vector4. local grey = vmath.vector4(0.5, 0.5, 0.5, 1.0) go.set("#my_label", "color", grey) -- ...and remove the outline, by setting its alpha to 0... go.set("#my_label", "outline.w", 0) -- ...and scale it x2 along x axis. local scale_x = go.get("#my_label", "scale.x") go.set("#my_label", "scale.x", scale_x * 2) end ``` ## Project configuration The *game.project* file has a few [project settings](#manuals:project-settings#label) related to labels. # Mesh component {#manuals:mesh} Defold is at its core a 3D engine. Even when you work with 2D material only all rendering is done in 3D, but orthographically projected onto the screen. Defold allows you to utilize full 3D content by adding and creating 3D meshes at run-time in your collections. You can build games in strictly 3D with only 3D assets, or you can mix 3D and 2D content as you wish. ## Creating a mesh component Mesh components are created just like any other game object component. You can do it two ways: - Create a *Mesh file* by `right-clicking` a location in the *Assets* browser and select `New... ▸ Mesh`. - Create the component embedded directly into a game object by `right-clicking` a game object in the *Outline* view and selecting `Add Component ▸ Mesh`. With the mesh created you need to specify a number of properties: ### Mesh properties Apart from the properties *Id*, *Position* and *Rotation* the following component specific properties exist: *Material* : The material to use for rendering the mesh. *Vertices* : A buffer file describing the mesh data per stream. *Primitive Type* : Lines, Triangles or Triangle Strip. *Position Stream* : This property should be the name of the *position* stream. The stream is automatically provided as input to the vertex shader. *Normal Stream* : This property should be the name of the *normal* stream. The stream is automatically provided as input to the vertex shader. *tex0* : Set this to texture to use for the mesh. ## Editor manipulation With the mesh component in place you are free to edit and manipulate the component and/or the encapsulating game object with the regular *Scene Editor* tools to move, rotate and scale the mesh to your liking. ## Runtime manipulation You can manipulate meshes at runtime using Defold buffers. Example of creating a cube from triangle strips: ```Lua -- cube local vertices = { 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0 } -- create a buffer with a position stream local buf = buffer.create(#vertices / 3, { { name = hash("position"), type=buffer.VALUE_TYPE_FLOAT32, count = 3 } }) -- get the position stream and write the vertices local positions = buffer.get_stream(buf, "position") for i, value in ipairs(vertices) do positions[i] = vertices[i] end -- set the buffer with the vertices on the mesh local res = go.get("#mesh", "vertices") resource.set_buffer(res, buf) ``` Refer to the [forum announcement post for more information](https://forum.defold.com/t/mesh-component-in-defold-1-2-169-beta/65137) on how to use the Mesh component, including sample projects and code snippets. ## Frustum culling Mesh components are not automatically culled due to their dynamic nature and the fact that it is not possible to know for sure how the positional data is encoded. In order to cull a mesh the axis-aligned bounding box of the mesh needs to be set as meta data on the buffer using 6 floats (AABB min/max): ```lua buffer.set_metadata(buf, hash("AABB"), { 0, 0, 0, 1, 1, 1 }, buffer.VALUE_TYPE_FLOAT32) ``` ## Material constants The default mesh material has the following constants that can be changed using [go.set()](https://defold.com/ref/stable/go/#go.set) or [go.animate()](https://defold.com/ref/stable/go/#go.animate) (refer to the [Material manual for more details](#manuals:material)). Examples: ```lua go.set("#mesh", "tint", vmath.vector4(1,0,0,1)) go.animate("#mesh", "tint", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(1,0,0,1), go.EASING_LINEAR, 2) ``` `tint` : The color tint of the mesh (`vector4`). The vector4 is used to represent the tint with x, y, z, and w corresponding to the red, green, blue and alpha tint. ## Vertex local vs world space If the Vertex Space setting of the mesh material is set to Local Space the data will be provided as-is to you in your shader, and you will have to transform vertices/normals as usual on the GPU. If the Vertex Space setting of the mesh material is set to World Space you have to either provide a default “position” and “normal”, stream, or you can select it from the dropdown, when editing the mesh. This is so that the engine can transform the data to world space for batching with other objects. # Model component {#manuals:model} Defold is at its core a 3D engine. Even when you work with 2D material only all rendering is done in 3D, but orthographically projected onto the screen. Defold allows you to utilize full 3D content by including 3D assets, or _Models_ into your collections. You can build games in strictly 3D with only 3D assets, or you can mix 3D and 2D content as you wish. ## Creating a model component Model components are created just like any other game object component. You can do it two ways: - Create a *Model file* by `right-clicking` a location in the *Assets* browser and select `New... ▸ Model`. - Create the component embedded directly into a game object by `right-clicking` a game object in the *Outline* view and selecting `Add Component ▸ Model`. With the model created you need to specify a number of properties: ### Model properties Apart from the properties *Id*, *Position* and *Rotation* the following component specific properties exist: *Mesh* : This property should refer to the glTF *.gltf* file that contains the mesh to use. If the file contains multiple meshes, only the first one is read. *Create GO Bones* : Check this to create a game object for every bone of the model. You can use the game objects to attach other game objects such as weapons to hand bones and so on. *Skeleton* : This property should refer to the glTF *.gltf* file that contains the skeleton to use for animation. Note that Defold requires a single root bone in your hierarchy. *Animations* : Set this to the *Animation Set File* that contains the animations you want to use on the model. *Default Animation* : This is the animation (from the animation set) that will be automatically played on the model. In addition to the properties above there will also be a field to assign a material for every mesh of the model: *Material* : Set this property to a material you have created that is suitable for a textured 3D object. There are a number of built-in materials that you can use as a starting point: * Use *model.material* for static non-instanced models * Use *model_instances.material* for static instanced models * Use *model_skinned.material* for skinned (animated) non-instanced models * Use *model_skinned_instances.material* for skinned (animated) instanced models Depending on the material there will be one or more texture properties: *Texture* : This property should point to the texture image file that you want applied to the object. ## Editor manipulation With the model component in place you are free to edit and manipulate the component and/or the encapsulating game object with the regular *Scene Editor* tools to move, rotate and scale the model to your liking. ## Runtime manipulation You can manipulate models in runtime through a number of different functions and properties (refer to the [API docs for usage](https://defold.com/ref/model/)). ### Runtime animation Defold provides powerful support for controlling animation in runtime. More in the [model animation manual](#manuals:model-animation): ```lua local play_properties = { blend_duration = 0.1 } model.play_anim("#model", "jump", go.PLAYBACK_ONCE_FORWARD, play_properties) ``` The animation playback cursor can be animated either by hand or through the property animation system: ```lua -- set the run animation model.play_anim("#model", "run", go.PLAYBACK_NONE) -- animate the cursor go.animate("#model", "cursor", go.PLAYBACK_LOOP_PINGPONG, 1, go.EASING_LINEAR, 10) ``` ### Changing properties A model also has a number of different properties that can be manipulated using `go.get()` and `go.set()`: `animation` : The current model animation (`hash`) (READ ONLY). You change animation using `model.play_anim()` (see above). `cursor` : The normalized animation cursor (`number`). `material` : The model material (`hash`). You can change this using a material resource property and `go.set()`. Refer to the [API reference for an example](https://defold.com/ref/model/#material). `playback_rate` : The animation playback rate (`number`). `textureN` : The model textures where N is 0-7 (`hash`). You can change this using a texture resource property and `go.set()`. Refer to the [API reference for an example](https://defold.com/ref/model/#textureN). ## Material 3D software commonly allows you to set properties on your object vertices, like coloring and texturing. This information goes into the glTF *.gltf* file that you export from your 3D software. Depending on the requirements of your game you will have to select and/or create appropriate and _performant_ materials for your objects. A material combines _shader programs_ with a set of parameters for rendering of the object. There are a number of built-in materials that you can use as a starting point: * Use *model.material* for static non-instanced models * Use *model_instances.material* for static instanced models * Use *model_skinned.material* for skinned (animated) non-instanced models * Use *model_skinned_instances.material* for skinned (animated) instanced models If you need to create custom materials for your models, see the [Material documentation](#manuals:material) for information. The [Shader manual](#manuals:shader) contains information on how shader programs work. ### Material constants The default model material has the following constants that can be changed using [go.set()](https://defold.com/ref/stable/go/#go.set) or [go.animate()](https://defold.com/ref/stable/go/#go.animate) (refer to the [Material manual for more details](#manuals:material)). Examples: ```lua go.set("#model", "tint", vmath.vector4(1,0,0,1)) go.animate("#model", "tint", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(1,0,0,1), go.EASING_LINEAR, 2) ``` `tint` : The color tint of the model (`vector4`). The vector4 is used to represent the tint with x, y, z, and w corresponding to the red, green, blue and alpha tint. ## Rendering The default render script is tailor made for 2D games and does not work with 3D models. But by copying the default render script and adding a handful of lines of code to the render script you can enable rendering of your models. For instance: ```lua function init(self) self.model_pred = render.predicate({"model"}) ... end function update() ... render.set_depth_mask(true) render.enable_state(render.STATE_DEPTH_TEST) render.set_projection(stretch_projection(-1000, 1000)) -- orthographic render.draw(self.model_pred) render.set_depth_mask(false) ... end ``` See the [Render documentation](#manuals:render) for details on how render scripts work. # Particle FX {#manuals:particlefx} Particle effects are used to visually enhance games. You can use them to create explosions, blood splatter, trails, weather or any other effect. Particle effects consists of a number of emitters and optional modifiers: Emitter : An emitter is a positioned shape that emits particles uniformly distributed over the shape. The emitter contains properties that controls the particle spawning as well as the image or animation, lifespan, color, shape and velocity of the individual particles. Modifier : A modifier affects the velocity of spawned particles to make them accelerate or slow down in a particular direction, move radially or swirl around a point. Modifiers can affect a single emitter's particles or a particular emitter. ## Creating an effect Select `New... ▸ Particle FX` from the context menu in the *Assets* browser. Name the new particle effect file. The editor will now open the file using the [Scene Editor](#manuals:editor). The *Outline* pane shows the default emitter. Select the emitter to bring up its properties in the *Properties* pane below. To add a new emitter to the effect, `right click` the root of the *Outline* and select `Add Emitter ▸ [type]` from the context menu. Note that you can change the type of the emitter in the emitter properties. To add a new modifier, `right click` the location of the modifier in the *Outline* (the effect root or a particular emitter) and select `Add Modifier`, then select the modifier type. A modifier that sits on the effect root (not childed to an emitter) affects all particles in the effect. A modifier that is added as a child to an emitter affects only that emitter. ## Previewing an effect * Select `View ▸ Play` from the menu to preview the effect. You may need to zoom out the camera to see the effect properly. * Select `View ▸ Play` again to pause the effect. * Select `View ▸ Stop` to stop the effect. Playing it again restarts it from its initial state. When editing an emitter or modifier the result is immediately visible in the editor, even with the effect paused: ## Emitter properties Id : Emitter identifier (used when setting render constants for specific emitters). Position/Rotation : Transform of the emitter relative the ParticleFX component. Play Mode : Controls how the emitter plays: - `Once` stops the emitter after reaching its duration. - `Loop` restarts the emitter after reaching its duration. Size Mode : Controls how flipbook animations will be sized: - `Auto` keeps the size of each flipbook animation frame to the source image. - `Manual` sets the particle size according to the size property. Emission Space : Which geometrical space the spawned particles will exist: - `World` moves the particles independent of the emitter. - `Emitter` moves the particles relative to the emitter. Duration : The number of seconds the emitter should emit particles. Start Delay : The number of seconds the emitter should wait before emitting particles. Start Offset : The number of seconds into the particle simulation the emitter should start, or in other words how long the emitter should prewarm the effect for. Image : The image file (Tile source or Atlas) to use for texturing and animating the particles. Animation : The animation from the *Image* file to use on the particles. Material : The material to use for shading the particles. Blend Mode : Available blend modes are `Alpha`, `Add` and `Multiply`. Max Particle Count : How many particles originating from this emitter that can exist at the same time. Emitter Type : The shape of the emitter - `Circle` emits particles from a random location inside a circle. The particles are directed outwards from the center. The circle diameter is defined by *Emitter Size X*. - `2D Cone` emits particles from a random location inside a flat cone (a triangle). The particles are directed out of the top of the cone. *Emitter Size X* defines the width of the top and *Y* defines the height. - `Box` emits particles from a random location inside a box. The particles are directed up along the box' local Y-axis. *Emitter Size X*, *Y* and *Z* defines width, height and depth respectively. For a 2D rectangle, keep the Z size at zero. - `Sphere` emits particles from a random location inside a sphere. The particles are directed outwards from the center. The sphere diameter is defined by *Emitter Size X*. - `Cone` emits particles from a random location inside a 3D cone. The particles are directed out through the top disc of the cone. *Emitter Size X* defines the diameter of the top disc and *Y* defines the height of the cone. Particle Orientation : How the emitted particles are oriented: - `Default` sets the orientation to unit orientation - `Initial Direction` keeps the initial orientation of the emitted particles. - `Movement Direction` adjusts the orientation of the particles according to their velocity. Inherit Velocity : A scale value of how much of the velocity of the emitter the particles should inherit. This value is only available when *Space* is set to `World`. The velocity of the emitter is estimated every frame. Stretch With Velocity : Check to scale any particle stretch in the direction of movement. ### Blend modes The *Blend Mode* property defines how the component graphics should be blended with the graphics behind it. These are the available blend modes and how they are calculated: Alpha : Normal blending: `src.a * src.rgb + (1 - src.a) * dst.rgb` Add : Brighten the background with the color values of the corresponding pixels of the component: `src.rgb + dst.rgb` Multiply : Darken the background with values of the corresponding pixels of the component: `src.rgb * dst.rgb` Screen : Opposite of Multiply. Brighten background and values of the corresponding pixels of the component: `src.rgb - dst.rgb * dst.rgb` ## Keyable emitter properties These properties have two fields: a value and a spread. The spread is a variation which is applied randomly for each spawned particle. E.g. if the value is 50 and the spread is 3, each spawned particle will get a value between 47 and 53 (50 +/- 3). By checking the key button, the value of the property is controlled by a curve over the duration of the emitter. To reset a keyed property, uncheck the key button. The *Curve Editor* (available among the tabs in the bottom view) is used to modify the curve. Keyed properties can't be edited in the *Properties* view, only in the *Curve Editor*. `Click and drag` the points and tangents to modify the shape of the curve. `Double-click` on the curve to add control points. To remove a control point, `double click` on it. To auto-zoom the Curve Editor to display all curves, press `F`. The following properties can be keyed over the play time of the emitter: Spawn Rate : The number of particles to emit per second. Emitter Size X/Y/Z : The dimensions of the emitter shape, see *Emitter Type* above. Particle Life Time : The lifespan of each spawned particle, in seconds. Initial Speed : The initial velocity of each spawned particle. Initial Size : The initial size of each spawned particle. If you set *Size Mode* to `Automatic` and use a flipbook animation as image source, this property is ignored. Initial Red/Green/Blue/Alpha : The initial color component tint values for the particles. Initial Rotation : The initial rotation values (in degrees) for the particles. Initial Stretch X/Y : The initial stretch values (in units) for the particles. Initial Angular Velocity : The initial angular velocity (in degrees/second) of each spawned particle. The following properties can be keyed over the life time of the particles: Life Scale : The scale value over each particle's life. Life Red/Green/Blue/Alpha : The color component tint value over each particle's life. Life Rotation : The rotation value (in degrees) over each particle's life. Life Stretch X/Y : The stretch value (in units) over each particle's life. Life Angular Velocity : The angular velocity (in degrees/second) over each particle's life. ## Modifiers There are four types of modifiers available that affect the velocity of particles: `Acceleration` : Acceleration in a general direction. `Drag` : Reduces the acceleration of particles proportional to the particle velocity. `Radial` : Either attracts or repels particles towards/from a position. `Vortex` : Affects particles in a circular or spiraling direction around its position. ## Modifier properties Position/Rotation : The transform of the modifier relative its parent. Magnitude : The amount of effect the modifier has on the particles. Max Distance : The maximum distance within which particles are affected at all by this modifier. Only used for Radial and Vortex. ## Controlling a particle effect To start and stop a particle effect from a script: ```lua -- start the effect component "particles" in the current game object particlefx.play("#particles") -- stop the effect component "particles" in the current game object particlefx.stop("#particles") ``` To start and stop a particle effect from a GUI script see the [GUI Particle FX manual](#manuals:gui-particlefx#controlling-the-effect) for more information. A particle effect will continue to emit particles even if the game object the particle effect component belonged to is deleted. See the [Particle FX reference documentation](https://defold.com/ref/particlefx) for more information. ## Material constants The default particle effect material has the following constants that can be changed using `particlefx.set_constant()` and reset using `particlefx.reset_constant()` (refer to the [Material manual for more details](#manuals:material)): `tint` : The color tint of the particle effect (`vector4`). The vector4 is used to represent the tint with x, y, z, and w corresponding to the red, green, blue and alpha tint. Refer to the [API reference for an example](https://defold.com/ref/particlefx/#particlefx.set_constant:url-constant-value). ## Project configuration The *game.project* file has a few [project settings](#manuals:project-settings#particle-fx) related to particles. # Sound {#manuals:sound} Defold's sound implementation is simple but powerful. There are only two concepts that you need to be aware of: Sound components : These components contain an actual sound that should be played and are able to play back the sound. Sound groups : Each sound component can be designated to belong to a _group_. Groups offer an easy way to manage sounds that belong together in an intuitive way. For instance, a group "sound_fx" can be set up and any sound belonging to that group can be ducked by a simple function call. ## Creating a sound component Sound components can only be instanced in-place in a game object. Create a new game object, right click on it and select `Add Component ▸ Sound` and press *OK*. The created component has a set of properties that should be set: *Sound* : Should be set to a sound file in your project. The file should be in _Wave_, _Ogg Vorbis_ or _Ogg Opus_ format. Defold supports sound files saved at 16bit bit depth. *Looping* : If checked the sound will play back in _Loopcount_ times or until explicitly stopped. *Loopcount* : The number of times a looping sound will play before stopping (0 means the sound should loop until explicitly stopped). *Group* : The name of the sound group the sound should belong to. If this property is left empty, the sound will be assigned to the built-in "master" group. *Gain* : You can set the gain for the sound directly on the component. This allows you to easily tweak the gain for a sound without going back to your sound program and performing a re-export. See below for details on how gain is calculated. *Pan* : You can set the pan value for the sound directly on the component. The pan must be a value between -1 (-45 degrees left) and 1 (45 degrees right). *Speed* : You can set the speed value for the sound directly on the component. A value of 1.0 is normal speed, 0.5 is half speed and 2.0 is double speed. ## Playing the sound When you have a sound component set up properly, you can cause it to play its sound by calling [`sound.play()`](https://defold.com/ref/sound/#sound.play:url-[play_properties]-[complete_function]): ```lua sound.play("go#sound", {delay = 1, gain = 0.5, pan = -1.0, speed = 1.25}) ``` A sound will continue to play even if the game object the sound component belonged to is deleted. You can call [`sound.stop()`](https://defold.com/ref/sound/#sound.stop:url) to stop the sound (see below). Each message sent to a component will cause it to play another instance of the sound, until the available sound buffer is full and the engine will print errors in the console. It is advised that you implement some sort of gating and sound grouping mechanism. ## Stopping the sound If you wish to stop playing a sound you can call [`sound.stop()`](https://defold.com/ref/sound/#sound.stop:url): ```lua sound.stop("go#sound") ``` ## Gain The sound system has 4 levels of gain: - The gain set on the sound component. - The gain set when starting the sound via a call to `sound.play()` or when changing the gain on the voice via a call to `sound.set_gain()`. - The gain set on the group via a [`sound.set_group_gain()`](https://defold.com/ref/sound#sound.set_group_gain) function call. - The gain set on the "master" group. This can be altered by `sound.set_group_gain(hash("master"))`. The output gain is the result of these 4 gains multiplied. The default gain is 1.0 everywhere (0 dB). ## Sound groups Any sound component with a sound group name specified will be put in a sound group with that name. If you don't specify a group the sound will be assigned to the "master" group. You can also explicitly set the group on a sound component to "master" which has the same effect. A few functions are available to get all available groups, get the string name, get and set gain, rms (see http://en.wikipedia.org/wiki/Root_mean_square) and peak gain. There is also a function that allows you to test if the target device's music player is running: ```lua -- If sound playing on this iPhone/Android device, silence everything if sound.is_music_playing() then for i, group_hash in ipairs(sound.get_groups()) do sound.set_group_gain(group_hash, 0) end end ``` The groups are identified with a hash value. The string name can be retrieved with [`sound.get_group_name()`](https://defold.com/ref/sound#sound.get_group_name) which can be used to display group names in development tools, for instance a mixer to test group levels. You should not write code that relies on the string value of a sound group since they are not available in release builds. All values are linear between 0 and 1.0 (0 dB). To convert to decibel, simply use the standard formula: ```math db = 20 \times \log \left( gain \right) ``` ```lua for i, group_hash in ipairs(sound.get_groups()) do -- The name string is only available in debug. Returns "unknown_*" in release. local name = sound.get_group_name(group_hash) local gain = sound.get_group_gain(group_hash) -- Convert to decibel. local db = 20 * math.log10(gain) -- Get RMS (gain Root Mean Square). Left and right channel separately. local left_rms, right_rms = sound.get_rms(group_hash, 2048 / 65536.0) left_rmsdb = 20 * math.log10(left_rms) right_rmsdb = 20 * math.log10(right_rms) -- Get gain peak. Left and right separately. left_peak, right_peak = sound.get_peak(group_hash, 2048 * 10 / 65536.0) left_peakdb = 20 * math.log10(left_peak) right_peakdb = 20 * math.log10(right_peak) end -- Set the master gain to +6 dB (math.pow(10, 6/20)). sound.set_group_gain("master", 1.995) ``` ## Gating sounds If your game plays the same sound on an event and that event is triggered often, you run the risk of playing the same sound two times or more almost at the same time. If that happens, the sounds will be _phase shifted_ which can result in some very noticeable artifacts. The easiest way to deal with this problem is to build a gate that filters sound messages and does not allow the same sound to be played more than once within a set interval: ```lua -- Don't allow the same sound to be played within "gate_time" interval. local gate_time = 0.3 function init(self) -- Store played sound timers in a table and count down each frame until they have been -- in the table for "gate_time" seconds. Then remove them. self.sounds = {} end function update(self, dt) -- Count down the stored timers for k,_ in pairs(self.sounds) do self.sounds[k] = self.sounds[k] - dt if self.sounds[k] < 0 then self.sounds[k] = nil end end end function on_message(self, message_id, message, sender) if message_id == hash("play_gated_sound") then -- Only play sounds that are not currently in the gating table. if self.sounds[message.soundcomponent] == nil then -- Store sound timer in table self.sounds[message.soundcomponent] = gate_time -- Play the sound sound.play(message.soundcomponent, { gain = message.gain }) else -- An attempt to play a sound was gated print("gated " .. message.soundcomponent) end end end ``` To use the gate, simply send it a `play_gated_sound` message and specify the target sound component and sound gain. The gate will call `sound.play()` with the target sound component if the gate is open: ```lua msg.post("/sound_gate#script", "play_gated_sound", { soundcomponent = "/sounds#explosion1", gain = 1.0 }) ``` It does not work to have the gate listen to `play_sound` messages since that name is reserved by the Defold engine. You will get unexpected behavior if you use reserved message names. ## Runtime manipulation You can manipulate sounds in runtime through a number of different properties (refer to the [API docs for usage](https://defold.com/ref/sound/)). The following properties can be manipulated using `go.get()` and `go.set()`: `gain` : The gain for the sound component (`number`). `pan` : The pan for the sound component (`number`). The pan must be a value between -1 (-45 degrees left) and 1 (45 degrees right). `speed` : The speed for the sound component (`number`). A value of 1.0 is normal speed, 0.5 is half speed and 2.0 is double speed. `sound` : The resource path to the sound (`hash`). You can use the resource path to change the sound using `resource.set_sound(path, buffer)`. Example: ```lua local boom = sys.load_resource("/sounds/boom.wav") local path = go.get("#sound", "sound") resource.set_sound(path, boom) ``` ## Project configuration The *game.project* file has a few [project settings](#manuals:project-settings#sound) related to sound components. ## Sound Streaming It is also possible to support [streaming sounds](#manuals:sound-streaming) # Sprites {#manuals:sprite} A Sprite component is a simple image or flipbook animation that is displayed on screen. The Sprite component can use either an [Atlas](#manuals:atlas) or a [Tile Source](#manuals:tilesource) for it's graphics. ## Sprite properties Apart from the properties *Id*, *Position* and *Rotation* the following component specific properties exist: *Image* : If the shader has a single sampler, this field is named `Image`. Otherwise, each slot is named after the texture sampler in the material. Each slot specifies the atlas or tilesource resource to use for the sprite on that texture sampler. *Default Animation* : The animation to use for the sprite. The animation information is taken from the first atlas or tilesource. *Material* : The material to use for rendering the sprite. *Blend Mode* : The blend mode to use when rendering the sprite. *Size Mode* : If set to `Automatic` the editor will set a size of the sprite. If set to `Manual` you can set the size yourself. *Slice 9* : Set to preserve the pixel size of the sprite's texture around the edges when the sprite is resized. ## Slice-9 texturing GUI box nodes and Sprite components sometimes feature elements that are context sensitive in regard to their size: panels and dialogs that need to be resized to fit the containing content or a health bar that need to be resized to show the remaining health of an enemy. These may cause visual problems when you apply texturing to the resized node or sprite. Normally, the engine scales the texture to fit the rectangular boundaries, but by defining slice-9 edge areas it is possible to limit what parts of the texture that should scale: The *Slice9* box node consists of 4 numbers that specify the number of pixels for the left, top, right and bottom margin that should not be regularly scaled: The margins are set clockwise, starting on the left edge: - Corner segments are never scaled. - Edge segments are scaled along a single axis. The left and right edge segments are scaled vertically. The top and bottom edge segments are scaled horizontally. - The central texture area is scaled horizontally and vertically as needed. The *Slice9* texture scaling described above is only applied when you change box node's or sprite's size: If you change scale parameter of the box node or sprite (or on the game object) - the node or sprite and texture is scaled without applying *Slice9* parameters. When using slice-9 texturing on Sprites the [Sprite Trim Mode of the image](#manuals:atlas) must be set to Off. ### Mipmaps and slice-9 Due to the way mipmapping works in the renderer, scaling of texture segments can sometimes exhibit artifacts. This happens when you _scale down_ segments below the original texture size. The renderer then selects a lower resolution mipmap for the segment, resulting in visual artifacts. To avoid this problem, make sure that the texture's segments that will be scaled are small enough never to be scaled down, only up. ### Blend modes The *Blend Mode* property defines how the component graphics should be blended with the graphics behind it. These are the available blend modes and how they are calculated: Alpha : Normal blending: `src.a * src.rgb + (1 - src.a) * dst.rgb` Add : Brighten the background with the color values of the corresponding pixels of the component: `src.rgb + dst.rgb` Multiply : Darken the background with values of the corresponding pixels of the component: `src.rgb * dst.rgb` Screen : Opposite of Multiply. Brighten background and values of the corresponding pixels of the component: `src.rgb - dst.rgb * dst.rgb` ## Runtime manipulation You can manipulate sprites in runtime through a number of different functions and properties (refer to the [API docs for usage](https://defold.com/ref/sprite/)). Functions: * `sprite.play_flipbook()` - Play an animation on a sprite component. * `sprite.set_hflip()` and `sprite.set_vflip()` - Set horizontal and vertical flipping on a sprite's animation. A sprite also has a number of different properties that can be manipulated using `go.get()` and `go.set()`: `cursor` : The normalized animation cursor (`number`). `image` : The sprite image (`hash`). You can change this using an atlas or tile source resource property and `go.set()`. Refer to the [API reference for an example](https://defold.com/ref/sprite/#image). `material` : The sprite material (`hash`). You can change this using a material resource property and `go.set()`. Refer to the [API reference for an example](https://defold.com/ref/sprite/#material). `playback_rate` : The animation playback rate (`number`). `scale` : The non-uniform scale of the sprite (`vector3`). `size` : The size of the sprite (`vector3`). Can only be changed if sprite size-mode is set to manual. ## Material constants The default sprite material has the following constants that can be changed using [go.set()](https://defold.com/ref/stable/go/#go.set) or [go.animate()](https://defold.com/ref/stable/go/#go.animate) (refer to the [Material manual for more details](#manuals:material)). Examples: ```lua go.set("#sprite", "tint", vmath.vector4(1,0,0,1)) go.animate("#sprite", "tint", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(1,0,0,1), go.EASING_LINEAR, 2) ``` `tint` : The color tint of the sprite (`vector4`). The vector4 is used to represent the tint with x, y, z, and w corresponding to the red, green, blue and alpha tint. ## Material attributes A sprite can override vertex attributes from the currently assigned material and will be passed into the vertex shader from the component (refer to the [Material manual for more details](#manuals:material)). The attributes specified in the material will show up as regular properties in the inspector and can be set on individual sprite components. If any of the attributes are overridden, it will show up as an overridden property and stored in the sprite file on disk: ## Project configuration The *game.project* file has a few [project settings](#manuals:project-settings#sprite) related to sprites. ## Multi textured sprites When a sprite uses multiple textures there are some things to note. ### Animations The animation data (fps, frame names) is currently taken from the first texture. We'll call this the "driving animation". The image id's of the driving animation are used to lookup the images in another texture. So it's important to make sure the frame ids match between textures. E.g. if your `diffuse.atlas` has a `run` animation like so: ``` run: /main/images/hero_run_color_1.png /main/images/hero_run_color_2.png ... ``` Then the frame id's would be `run/hero_run_color_1` which is not likely to be found in for instance a `normal.atlas`: ``` run: /main/images/hero_run_normal_1.png /main/images/hero_run_normal_2.png ... ``` So we use the `Rename patterns` in the [atlas](#manuals:material) to rename them. Set `_color=` and `_normal=` in the corresponding atlases, and you'll get frame names like this in both atlases: ``` run/hero_run_1 run/hero_run_2 ... ``` ### UVs The UVs are taken from the first texture. Since there is only one set of vertices, we cannot guarantee a good match anyways if the secondary textures have either more UV coordinates or a different shape. This is important to note, so make sure the images have similar enough shapes, or you might experience texture bleeding. The dimensions of the images in each texture may be different. # Tile map {#manuals:tilemap} A *Tile Map* is a component that allows you to assemble, or paint, tiles from a *Tile Source* onto a large grid area. Tile maps are commonly used to build game level environments. You can also use the *Collision Shapes* from the tile source in your maps for collision detection and physics simulation ([example](https://defold.com/examples/tilemap/collisions/)). Before you can create a tile map you need to create a Tile Source. Refer to the [Tile Source manual](#manuals:tilesource) to learn how to create a Tile Source. ## Creating a tile map To create a new tile map: - `Right click` a location in the *Assets* browser, then select `New... ▸ Tile Map`). - Name the file. - The new tile map automatically opens in the tile map editor. - Set the *Tile Source* property to a tile source file that you have prepared. To paint tiles on your tile map: 1. Select or create a *Layer* to paint on in the *Outline* view. 2. Select a tile to use as a brush (press `Space` to show the tile palette) or select a few tiles by clicking and dragging in the palette to create a rectangle brush with multiple tiles. 3. Paint with the selected brush. To erase a tile, either pick an empty tile and use it as brush, or select the eraser (`Edit ▸ Select Eraser`). You can pick tiles directly from a layer and use the selection as a brush. Hold `Shift` and click a tile to pick it up as the current brush. While holding `Shift` you can also click and drag to select a block of tiles to use as a larger brush. Also, it is possible to cut tiles in a similar way by holding `Shift+Ctrl` or erase them by holding `Shift+Alt`. For clockwise brush rotation, use `Z`. Use `X` for horizontal flipping and `Y` for vertical flipping of the brush. ## Adding a tile map to your game To add a tile map to your game: 1. Create a game object to hold the tile map component. The game object can be in a file or created directly in a collection. 2. Right-click the root of the game object and select `Add Component File`. 3. Select the tile map file. ## Runtime manipulation You can manipulate tilemaps in runtime through a number of different functions and properties (refer to the [API docs for usage](https://defold.com/ref/tilemap/)). ### Changing tiles from script You can read and write the content of a tile map dynamically while your game is running. To do so, use the [`tilemap.get_tile()`](https://defold.com/ref/tilemap/#tilemap.get_tile) and [`tilemap.set_tile()`](https://defold.com/ref/tilemap/#tilemap.set_tile) functions: ```lua local tile = tilemap.get_tile("/level#map", "ground", x, y) if tile == 2 then -- Replace grass-tile (2) with dangerous hole tile (number 4). tilemap.set_tile("/level#map", "ground", x, y, 4) end ``` ## Tilemap properties Apart from the properties *Id*, *Position*, *Rotation* and *Scale* the following component specific properties exist: *Tile Source* : The tilesource resource to use for the tilemap. *Material* : The material to use for rendering the tilemap. *Blend Mode* : The blend mode to use when rendering the tilemap. ### Blend modes The *Blend Mode* property defines how the component graphics should be blended with the graphics behind it. These are the available blend modes and how they are calculated: Alpha : Normal blending: `src.a * src.rgb + (1 - src.a) * dst.rgb` Add : Brighten the background with the color values of the corresponding pixels of the component: `src.rgb + dst.rgb` Multiply : Darken the background with values of the corresponding pixels of the component: `src.rgb * dst.rgb` Screen : Opposite of Multiply. Brighten background and values of the corresponding pixels of the component: `src.rgb - dst.rgb * dst.rgb` ### Changing properties A tilemap has a number of different properties that can be manipulated using `go.get()` and `go.set()`: `tile_source` : The tile map tile source (`hash`). You can change this using a tile source resource property and `go.set()`. Refer to the [API reference for an example](https://defold.com/ref/tilemap/#tile_source). `material` : The tile map material (`hash`). You can change this using a material resource property and `go.set()`. Refer to the [API reference for an example](https://defold.com/ref/tilemap/#material). ### Material constants The default tilemap material has the following constants that can be changed using [go.set()](https://defold.com/ref/stable/go/#go.set) or [go.animate()](https://defold.com/ref/stable/go/#go.animate) (refer to the [Material manual for more details](#manuals:material)). Examples: ```lua go.set("#tilemap", "tint", vmath.vector4(1,0,0,1)) go.animate("#tilemap", "tint", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(1,0,0,1), go.EASING_LINEAR, 2) ``` `tint` : The color tint of the tile map (`vector4`). The vector4 is used to represent the tint with x, y, z, and w corresponding to the red, green, blue and alpha tint. ## Project configuration The *game.project* file has a few [project settings](#manuals:project-settings#tilemap) related to tilemaps. ## External tools There are external map/level editors that can export directly to Defold tilemaps: ### Tiled [Tiled](https://www.mapeditor.org/) is a well-known and widely used map editor for orthogonal, isometric and hexagonal maps. Tiled has support for a wide array of features and can [export directly to Defold](https://doc.mapeditor.org/en/stable/manual/export-defold/). Learn more about how to export tilemap data and additional meta-data in [this blog post by Defold user "goeshard"](https://goeshard.org/2025/01/01/using-tiled-object-layers-with-defold-tilemaps/) ### Tilesetter [Tilesetter](https://www.tilesetter.org/docs/exporting#defold) can be used to automatically create full tilesets from simple base tiles and it has a map editor which can export directly to Defold. # GUI {#manuals:gui} Defold provides you with a custom GUI editor and powerful scripting possibilities that are tailor made for the construction and implementation of user interfaces. A graphical user interface in Defold is a component that you build and attach to a game object and place in a collection. This component has the following properties: * It has simple, but powerful, layout features that allow resolution and aspect ratio independent rendering of your user interface. * It can have logic behavior attached to it through a *GUI script*. * It is (by default) rendered on top of other content, independent of camera view so even if you have a moving camera, your GUI elements will stay put on the screen. The rendering behavior can be changed. GUI components are rendered independently of the game view. Because of this it is not placed in a particular location in the collection editor, nor does it have a visual representation in the collection editor. However, GUI components have to reside in a game object that has a location in a collection. Changing that location has no effect on the GUI. ## Creating a GUI component GUI components are created from a GUI scene prototype file (also known as "prefabs" or "blueprints" in other engines). To create a new GUI component, `right click` a location in the *Assets* browser and select `New ▸ Gui`. Type a name for the new GUI file and press `Ok`. Defold now automatically opens the file in the GUI scene editor. The *Outline* lists all the GUI's content: it's list of nodes and any dependencies (see below). The central editing area shows the GUI. The toolbar in the top right corner of the editing area contains *Move*, *Rotate* and *Scale* tools, as well as a [layout](#manuals:gui-layouts) selector. A white rectangle shows the bounds of the currently selected layout, of the default display width and height as set in the project settings. ## Gui properties Selecting the root "Gui" node in the *Outline* shows the *Properties* for the GUI component: *Script* : The GUI script bound to this GUI component. *Material* : The material used when rendering this GUI. Note that it is also possible to add multiple materials to a Gui from the Outline panel and assign these to individual nodes. *Adjust Reference* : Controls how each node's *Adjust Mode* should be calculated: - `Per Node` adjusts each node against the adjusted size of the parent node, or the resized screen. - `Disable` turns off node adjust mode. This forces all nodes to keep their set size. *Current Nodes* : The number of nodes currently being used in this GUI. *Max Nodes* : The maximum number of nodes for this GUI. *Max Dynamic Textures* : The maximum number of textures that can be created using [`gui.new_texture()`](https://defold.com/ref/stable/gui/#gui.new_texture:texture_id-width-height-type-buffer-flip) ## Runtime manipulation You can manipulate GUI properties in runtime from a script component using `go.get()` and `go.set()`: Fonts : Get or set a font used in a GUI. ```lua go.property("mybigfont", resource.font("/assets/mybig.font")) function init(self) -- get the font file currently assigned to the font with id 'default' print(go.get("#gui", "fonts", { key = "default" })) -- /builtins/fonts/default.font -- set the font with id 'default' to the font file assigned to the resource property 'mybigfont' go.set("#gui", "fonts", self.mybigfont, { key = "default" }) -- get the new font file assigned to the font with id 'default' print(go.get("#gui", "fonts", { key = "default" })) -- /assets/mybig.font end ``` Materials : Get or set a material used in a GUI. ```lua go.property("myeffect", resource.material("/assets/myeffect.material")) function init(self) -- get the material file currently assigned to the material with id 'effect' print(go.get("#gui", "materials", { key = "effect" })) -- /effect.material -- set the material id 'effect' to the material file assigned to the resource property 'myeffect' go.set("#gui", "materials", self.myeffect, { key = "effect" }) -- get the new material file assigned to the material with id 'effect' print(go.get("#gui", "materials", { key = "effect" })) -- /assets/myeffect.material end ``` Textures : Get or set a texture (atlas) used in a GUI. ```lua go.property("mytheme", resource.atlas("/assets/mytheme.atlas")) function init(self) -- get the texture file currently assigned to the texture with id 'theme' print(go.get("#gui", "textures", { key = "theme" })) -- /theme.atlas -- set the texture with id 'theme' to the texture file assigned to the resource property 'mytheme' go.set("#gui", "textures", self.mytheme, { key = "theme" }) -- get the new texture file assigned to the texture with id 'theme' print(go.get("#gui", "textures", { key = "theme" })) -- /assets/mytheme.atlas end ``` ## Dependencies The resource tree in a Defold game is static so any dependencies that you need for your GUI nodes need to be added to the component. The *Outline* groups all dependencies by type under "folders": To add a new dependency, drag and drop it from the *Asset* pane to the editor view. Alternatively, `right click` the "Gui" root in the *Outline*, then select `Add ▸ [type]` from the popup context menu. You can also `right click` on the folder icon for the type you want to add and select `Add ▸ [type]`. ## Node types A GUI component is built from a set of nodes. Nodes are simple elements. They can be translated (moved, scaled and rotated) and ordered in parent-child hierarchies either in the editor or at runtime through scripting. The following node types exist: Box node : Rectangular node with either a single color, texture or flip-book animation. See the [Box node documentation](#manuals:gui-box) for details. Text node : Displays text. See the [Text node documentation](#manuals:gui-text) for details. Pie node : A circular or ellipsoid node that can be partially filled or inverted. A See the [Pie node documentation](#manuals:gui-pie) for details. Template node : Templates are used to create instances based on other GUI scene files. See the [Template node documentation](#manuals:gui-template) for details. ParticleFX node : Plays a particle effect. See the [ParticleFX node documentation](#manuals:gui-particlefx) for details. Add nodes by right-clicking on the *Nodes* folder and selecting `Add ▸` and then `Box`, `Text`, `Pie`, `Template` or `ParticleFx`. You can also press `A` and select the type you want to add to the GUI. ## Node properties Each node has an extensive set of properties that control its appearance: Id : The identity of the node. This name has to be unique within the GUI scene. Position, Rotation and Scale : Governs the location, orientation and stretching of the node. You can use the *Move*, *Rotate* and *Scale* tools to change these values. The values can be animated from script ([learn more](#manuals:property-animation)). Size (box, text and pie nodes) : The size of the node is automatic by default but by setting the *Size Mode* to `Manual` you can alter the value. The size defines the bounds of the node and is used when doing input picking. This value can be animated from script ([learn more](#manuals:property-animation)). Size Mode (box and pie nodes) : If set to `Automatic` the editor will set a size for the node. If set to `Manual` you can set the size yourself. Enabled : If unchecked, the node is not rendered, not animated and can not be picked using `gui.pick_node()`. Use `gui.set_enabled()` and `gui.is_enabled()` to programmatically change and check this property. Visible : If unchecked, the node is not rendered, but can still be animated and picked using `gui.pick_node()`. Use `gui.set_visible()` and `gui.get_visible()` to programmatically change and check this property. Text (text nodes) : The text to display on the node. Line Break (text nodes) : Set for text to wrap according to the width of the node. Font (text nodes) : The font to use when rendering the text. Texture (box and pie nodes) : The texture to draw on the node. This is a reference to an image or animation in an atlas or tile source. Material (box, pie nodes, text and particlefx nodes) : The material to use when drawing the node. This can either be a material added to the Materials section of the outline or left blank to use the default material assigned to the GUI component. Slice 9 (box nodes) : Set to preserve the pixel size of the node's texture around the edges when the node is resized. See the [Box node documentation](#manuals:gui-box) for details. Inner Radius (pie nodes) : The inner radius of the node, expressed along the X axis. See the [Pie node documentation](#manuals:gui-pie) for details. Outer Bounds (pie nodes) : Controls the behavior of the outer bounds. See the [Pie node documentation](#manuals:gui-pie) for details. Perimeter Vertices (pie nodes) : The number of segments that will be used to build the shape. See the [Pie node documentation](#manuals:gui-pie) for details. Pie Fill Angle (pie nodes) : How much of the pie should be filled. See the [Pie node documentation](#manuals:gui-pie) for details. Template (template nodes) : The GUI scene file to use as template for the node. See the [Template node documentation](#manuals:gui-template) for details. ParticleFX (particlefx nodes) : The particle effect to use on this node. See the [ParticleFX node documentation](#manuals:gui-particlefx) for details. Color : The color of the node. If the node is textured, the color tints the texture. The color can be animated from script ([learn more](#manuals:property-animation)). Alpha : The translucency of the node. The alpha value can be animated from script ([learn more](#manuals:property-animation)). Inherit Alpha : Setting this checkbox makes a node inherit the alpha value of the parent node. The node's alpha value is then multiplied with the parent's alpha value. Leading (text nodes) : A scaling number for the line spacing. A value of `0` gives no line spacing. `1` (the default) is normal line spacing. Tracking (text nodes) : A scaling number for the letter spacing. Defaults to 0. Layer : Assigning a layer to the node overrides the normal draw order and instead follows the layer order. See below for details. Blend mode : Controls how the graphics of the node is blended with background graphics: - `Alpha` alpha blends the pixel values of the node with the background. This corresponds to "Normal" blend mode in graphics software. - `Add` adds the pixel values of the node with the background. This corresponds to "Linear dodge" in some graphics software. - `Multiply` multiplies the pixel values of the node with the background. - `Screen` inversely multiplies the pixel values of the node with the background. This corresponds to "Screen" blend mode in graphics software. Pivot : Sets the pivot point for the node. This can be seen as the "center point" of the node. Any rotation, scaling or size change will happen around this point. Possible values are `Center`, `North`, `South`, `East`, `West`, `North West`, `North East`, `South West` or `South East`. If you change the pivot of a node, the node will be moved so that the new pivot will be at the node's position. Text nodes are aligned so that `Center` sets the text center-aligned, `West` sets the text left-aligned and `East` sets the text right-aligned. X Anchor, Y Anchor : Anchoring controls how the node's vertical and horizontal position is altered when the scene boundaries, or the parent node's boundaries are stretched to fit the physical screen size. The following anchoring modes are available: - `None` (for both *X Anchor* and *Y Anchor*) keeps the node's position from the center of the parent node or scene, relative to it's *adjusted* size. - `Left` or `Right` (*X Anchor*) scales the horizontal position of the node so it keeps the position from the left and right edges of the parent node or scene at the same percentage. - `Top` or `Bottom` (*Y Anchor*) scales the vertical position of the node so it keeps the position from the top and bottom edges of the parent node or scene at the same percentage. Adjust Mode : Sets the adjust mode for the node. The adjust mode setting controls what happens to a node when the scene boundaries, or the parent node's boundaries, are adjusted to fit the physical screen size. A node created in a scene where the logical resolution is a typical landscape resolution: Fitting the scene to a portrait screen causes the scene to be stretched. Each node's bounding box is similarly stretched. However, by setting the adjust mode, the aspect ratio of the node's content can be kept intact. The following modes are available: - `Fit` scales the node content so that it is equal to the stretched bounding box width or height, whichever is smallest. In other words, the content will fit inside the stretched node bounding box. - `Zoom` scales the node content so that it is equal to the stretched bounding box width or height, whichever is largest. In other words, the content will fully cover the stretched node bounding box. - `Stretch` stretches the node content so it fills the stretched node bounding box. If the GUI scene property *Adjust Reference* is set to `Disabled`, this setting will be ignored. Clipping Mode (box and pie nodes) : Sets the clipping mode on the node: - `None` renders the node as usual. - `Stencil` makes the node boundaries define a stencil mask that is used to clip the node's child nodes. See the [GUI clipping manual](#manuals:gui-clipping) for details. Clipping Visible (box and pie nodes) : Set to render the node's content in the stencil area. See the [GUI clipping manual](#manuals:gui-clipping) for details. Clipping Inverted (box and pie nodes) : Invert the stencil mask. See the [GUI clipping manual](#manuals:gui-clipping) for details. ## Pivot, Anchors and Adjust Mode The combination of Pivot, Anchors and Adjust Mode properties allows for a very flexible design of GUIs but it can be somewhat hard to understand how it all works without looking at a concrete example. Let's take this GUI mockup created for a 640x1136 screen as an example: The UI is created with X and Y Anchors set to None and the Adjust Mode for each node is left at the default value of Fit. The Pivot point for the top panel is North, the pivot for the bottom panel is South and the pivot point for the bars in the top panel are set to West. The rest of the nodes have pivot points set to Center. If we resize the window to make it wider this is what happens: Now, what if we want the top and bottom bars to always be as wide as the screen? We can change the Adjust Mode for the grey background panels at the top and bottom to Stretch: This is better. The grey background panels will now always stretch to the width of the window, but the bars in the top panel as well as the two boxes at the bottom aren't positioned properly. If we want to keep the bars at the top positioned to the left we need to change the X Anchor from None to Left: That is exactly as we want it for the top panel. The bars in the top panel already had their Pivot points set to West which means that they will position themselves nicely with the left/west edge of the bars (Pivot) anchored to the left edge of the parent panel (X Anchor). Now, if we set the X Anchor to Left for the box on the left and the X Anchor to Right for the box on the right we get the following result: This is not quite the expected result. The two boxes should stay as close to the left and right edges as the two bars did in the top panel. The reason for this is that the Pivot point is wrong: Both boxes have a Pivot point set to Center. What this means is that when the screen becomes wider the center point (the pivot point) of the boxes will stay at the same relative distance from the edges. In the case of the left box it was 17% from the left edge with the original 640x1136 window: When the screen is resized the center point of the left box remains at the same distance of 17% from the left edge: If we change the Pivot point from Center to West for the box on the left and to East for the box on the right and reposition the boxes we get the result we're after even when the screen is resized: ## Draw order All nodes are rendered in the order they are listed under the "Nodes" folder. The node at the top of the list is drawn first and will thus appear behind every other node. The last node in the list is drawn last, meaning it will appear in front of all other nodes. Altering the Z-value on a node does not control its draw order; however, if you set the Z-value outside of your render script's render range the node will no longer be rendered to screen. You can override the index ordering of nodes with layers (see below). Select a node and press `Alt + Up/Down` to move a node up or down and change its index order. The draw order can be changed in script: ```lua local bean_node = gui.get_node("bean") local shield_node = gui.get_node("shield") if gui.get_index(shield_node) < gui.get_index(bean_node) then gui.move_above(shield_node, bean_node) end ``` ## Parent-child hierarchies A node is made the child of another node by dragging it onto the node that you wish to be the child's parent. A node with a parent inherits the transform (position, rotation and scale) applied to the parent and relative to the parent pivot. Parents are drawn before their children. Use layers to change the draw order of parent and child nodes and to optimize the rendering of nodes (see below). ## Layers and draw calls Layers give fine grained control over how nodes are drawn and can be used to reduce the number of draw calls the engine must create to draw a GUI scene. When the engine is about to draw the nodes of a GUI scene, it groups the nodes into draw call batches based on the following conditions: - The nodes must use the same type. - The nodes must use the same atlas or tile source. - The nodes must be rendered with the same blend mode. - They must use same font. If a node differs from the previous one on any of these points, it will break the batch and create another draw call. Clipping nodes always break the batch and each stencil scope also breaks the batch. The ability to arrange nodes in hierarchies makes it easy to group nodes into manageable units. But hierarchies can effectively break batch rendering if you mix different node types: When the rendering pipeline walks through the list of nodes, it is forced to set up a separate batch for each separate node because the types are different. All in all these three buttons will require six draw calls. By assigning layers to the nodes, they can be ordered differently, allowing the render pipeline to group the nodes together in fewer draw calls. Start by adding the layers you need to the scene. `Right click` the "Layers" folder icon in the *Outline* and select `Add ▸ Layer`. Mark the new layer and assign it a *Name* property in the *Properties* view. Then set the *Layer* property on each node to the corresponding layer. The layer drawing order takes precedence over the regular indexed node order, so setting the button graphics box-nodes to "graphics" and the button text nodes to "text" will result in the following draw order: * First all nodes in the "graphics" layer, from the top: 1. "button-1" 2. "button-2" 3. "button-3" * Then all nodes in the "text" layer, from the top: 4. "button-text-1" 5. "button-text-2" 6. "button-text-3" The nodes can now be batched into two draw calls, instead of six. A major performance win! Note that a child node with unset layer will implicitly inherit the layer setting of its parent node. Not setting a layer on a node implicitly adds it to the "null" layer, which is drawn before any other layer. # GUI box nodes {#manuals:gui-box} A box node is a rectangle filled with a color or a texture or animation. ## Adding box nodes Add new box nodes by either `right clicking` in the *Outline* and selecting `Add ▸ Box`, or press `A` and select `Box`. You can use images and animations from atlases or tile sources that has been added to the GUI. You add textures by `right clicking` the *Textures* folder icon in the *Outline* and selecting `Add ▸ Textures...`. Then set the *Texture* property on the box node: Note that the color of the box node will tint the graphics. The tint color is multiplied onto the image data, meaning that if you set the color to white (the default) no tint is applied. Box nodes are always rendered, even if they do not have a texture assigned to them, or have their alpha set to `0`, or are sized `0, 0, 0`. Box nodes should always have a texture assigned to them so the renderer can batch them properly and reduce the number of draw-calls. ## Playing animations Box nodes can play animations from atlases or tile sources. Refer to the [flipbook animation manual](#manuals:flipbook-animation) to learn more. ## Slice-9 texturing GUI box nodes and Sprite components sometimes feature elements that are context sensitive in regard to their size: panels and dialogs that need to be resized to fit the containing content or a health bar that need to be resized to show the remaining health of an enemy. These may cause visual problems when you apply texturing to the resized node or sprite. Normally, the engine scales the texture to fit the rectangular boundaries, but by defining slice-9 edge areas it is possible to limit what parts of the texture that should scale: The *Slice9* box node consists of 4 numbers that specify the number of pixels for the left, top, right and bottom margin that should not be regularly scaled: The margins are set clockwise, starting on the left edge: - Corner segments are never scaled. - Edge segments are scaled along a single axis. The left and right edge segments are scaled vertically. The top and bottom edge segments are scaled horizontally. - The central texture area is scaled horizontally and vertically as needed. The *Slice9* texture scaling described above is only applied when you change box node's or sprite's size: If you change scale parameter of the box node or sprite (or on the game object) - the node or sprite and texture is scaled without applying *Slice9* parameters. When using slice-9 texturing on Sprites the [Sprite Trim Mode of the image](#manuals:atlas) must be set to Off. ### Mipmaps and slice-9 Due to the way mipmapping works in the renderer, scaling of texture segments can sometimes exhibit artifacts. This happens when you _scale down_ segments below the original texture size. The renderer then selects a lower resolution mipmap for the segment, resulting in visual artifacts. To avoid this problem, make sure that the texture's segments that will be scaled are small enough never to be scaled down, only up. # GUI text nodes {#manuals:gui-text} Defold supports a specific type of GUI node that allows text to be rendered in a GUI scene. Any font resource added to a project can be used for text node rendering. ## Adding text nodes The fonts that you wish to use in GUI text nodes must be added to the GUI component. Either right-click the *Fonts* folder, use the `GUI` top menu or press the corresponding keyboard shortcut. Text nodes have a set of special properties: *Font* : Any text node you create must have the *Font* property set. *Text* : This property contains the text displayed. *Line Break* : Text alignment follows the pivot setting and setting this property allows the text to flow over several lines. The width of the node determines where the text will wrap. ## Alignment By setting the node pivot you can change the alignment mode for the text. *Center* : If the pivot is set to `Center`, `North` or `South`, the text is center-aligned. *Left* : If the pivot is set to any of the `West` modes, the text is left-aligned. *Right* : If the pivot is set to any of the `East` modes, the text is right-aligned. ## Modifying text nodes in runtime Text nodes respond to any generic node manipulation functions for setting size, pivot, color and so forth. A few text node only functions exist: * To change the font of a text node, use the [`gui.set_font()`](https://defold.com/ref/gui/#gui.set_font) function. * To change the line break behavior of a text node, use the [`gui.set_line_break()`](https://defold.com/ref/gui/#gui.set_line_break) function. * To change the content of a text node, use the [`gui.set_text()`](https://defold.com/ref/gui/#gui.set_text) function. ```lua function on_message(self, message_id, message, sender) if message_id == hash("set_score") then local s = gui.get_node("score") gui.set_text(s, message.score) end end ``` # GUI pie nodes {#manuals:gui-pie} Pie nodes are used to create circular or ellipsoid objects ranging from plain circles to pies and square doughnut shapes. ## Creating a pie node `Right click` the *Nodes* section in the *Outline* and select `Add ▸ Pie`. The new pie node is selected and you can modify its properties. The following properties are unique to pie nodes: Inner Radius : The inner radius of the node, expressed along the X axis. Outer Bounds : The shape of the outer bounds of the node. - `Ellipse` will extend the node to the outer radius. - `Rectangle` will extend the node to the node's bounding box. Perimeter Vertices : The number of segments that will be used to build the shape, expressed as the number of vertices required to fully circumscribe the 360 degree perimeter of the node. Pie Fill Angle : How much of the pie should be filled. Expressed as a counter-clockwise angle starting from the right. If you set a texture on the node, the texture image is applied flat, with the corners of the texture correlating to the corners of the node bounding box. ## Modify pie nodes at runtime Pie nodes respond to any generic node manipulation functions for setting size, pivot, color and so forth. A few pie node only functions and properties exist: ```lua local pienode = gui.get_node("my_pie_node") -- get the outer bounds local fill_angle = gui.get_fill_angle(pienode) -- increase perimeter vertices local vertices = gui.get_perimeter_vertices(pienode) gui.set_perimeter_vertices(pienode, vertices + 1) -- change outer bounds gui.set_outer_bounds(pienode, gui.PIEBOUNDS_RECTANGLE) -- animate the inner radius gui.animate(pienode, "inner_radius", 100, gui.EASING_INOUTSINE, 2, 0, nil, gui.PLAYBACK_LOOP_PINGPONG) ``` # GUI ParticleFX nodes {#manuals:gui-particlefx} A particle effect node is used to play particle effect systems in the GUI screen space. ## Adding Particle FX nodes Add new particle nodes by either `right clicking` in the *Outline* and selecting `Add ▸ ParticleFX`, or press `A` and select `ParticleFX`. You can use particle effects that you have added to the GUI as source for the effect. Add particle effects by `right clicking` the *Particle FX* folder icon in the *Outline* and selecting `Add ▸ Particle FX...`. Then set the *Particlefx* property on the node: ## Controlling the effect You can start and stop the effect by controlling the node from a script: ```lua -- start the particle effect local particles_node = gui.get_node("particlefx") gui.play_particlefx(particles_node) ``` ```lua -- stop the particle effect local particles_node = gui.get_node("particlefx") gui.stop_particlefx(particles_node) ``` See the [Particle FX manual](#manuals:particlefx) for details on how particle effects work. # GUI template nodes {#manuals:gui-template} GUI template nodes provide a powerful mechanism to create reusable GUI components based on shared templates or "prefabs". This manual explains the feature and how to use it. A GUI template is a GUI scene that is instantiated, node for node, in another GUI scene. Any property values in the original template nodes can then be overridden. ## Creating a template A GUI template is a plain GUI scene so it is created just like any other GUI scene. `Right click` a location in the *Assets* pane and select `New... ▸ Gui`. Create the template and save it. Note that the nodes of the instance will be placed relative to origin so it is a good idea to create the template at position 0, 0, 0. ## Creating instances from a template You can create any number of instances based on the instance. Create or open the GUI scene where you want to place the template, then `right click` the *Nodes* section in the *Outline* and select `Add ▸ Template`. Set the *Template* property to the template GUI scene file. You can add any number of template instances, and for each instance you can override the properties of each node and change instance node's position, coloring, size, texture and so forth. Any property that you change is marked blue in the editor. Press the reset button by the property to set its value to the template value: Any node that has overridden properties is also colored blue in the *Outline*: The template instance is listed as a collapsible entry in the *Outline* view. However, it is important to note that this item in the outline *is not a node*. The template instance does not exist in runtime either, but all nodes that are part of the instance does. Nodes that are part of a template instance are automatically named with a prefix and a slash (`"/"`) attached to their *Id*. The prefix is the *Id* set in the template instance. ## Modifying templates in runtime Scripts that manipulate or query nodes added through the templating mechanism only need to consider the naming of instance nodes and include the template instance *Id* as a node name prefix: ```lua if gui.pick_node(gui.get_node("button_1/button"), x, y) then -- Do something... end ``` There is no node corresponding to the template instance itself. If you need a root node for an instance, add it to the template. If a script is associated with a template GUI scene, the script is not part of the instance node tree. You may attach one single script to each GUI scene so your script logic needs to sit on the GUI scene where you have instantiated your templates. # GUI scripts {#manuals:gui-script} To control the logic of your GUI and animate nodes you use Lua scripts. GUI scripts work the same as regular game object scripts, but are saved as a different file type and have access to a different set of functions: the `gui` module functions. ## Adding a script to a GUI To add a script to a GUI, first create a GUI script file by `right clicking` a location in the *Assets* browser and selecting `New ▸ Gui Script` from the popup context menu. The editor automatically opens the new script file. It is based on a template and comes equipped with empty lifecycle functions, just like game object scripts: ```lua function init(self) -- Add initialization code here -- Remove this function if not needed end function final(self) -- Add finalization code here -- Remove this function if not needed end function update(self, dt) -- Add update code here -- Remove this function if not needed end function on_message(self, message_id, message, sender) -- Add message-handling code here -- Remove this function if not needed end function on_input(self, action_id, action) -- Add input-handling code here -- Remove this function if not needed end function on_reload(self) -- Add input-handling code here -- Remove this function if not needed end ``` To attach the script to a GUI component, open the GUI component prototype file (also known as "prefabs" or "blueprints" in other engines) and select the root in the *Outline* to bring up GUI *Properties*. Set the *Script* property to the script file If the GUI component has been added to a game object somewhere in your game, the script will now run. ## The "gui" namespace GUI scripts have access to the `gui` name space and [all the gui functions](https://defold.com/ref/gui). The `go` namespace is not available so you will need to separate game object logic into script components and communicate between the GUI and game object scripts. Any attempt to use the `go` functions will cause an error: ```lua function init(self) local id = go.get_id() end ``` ```txt ERROR:SCRIPT: /main/my_gui.gui_script:2: You can only access go.* functions and values from a script instance (.script file) stack traceback: [C]: in function 'get_id' /main/my_gui.gui_script:2: in function ``` ## Message passing Any GUI component with a script attached is able to communicate with other objects in your game runtime environment through message passing, it will behave like any other script component. You address the GUI component like you would any other script component: ```lua local stats = { score = 4711, stars = 3, health = 6 } msg.post("hud#gui", "set_stats", stats) ``` ## Addressing nodes GUI nodes can be manipulated by a GUI script attached to the component. Each node must have a unique *Id* that is set in the editor: The *Id* allows a script to get hold of a reference to the node and manipulate it with the [gui namespace functions](https://defold.com/ref/gui): ```lua -- extend the health bar by 10 units local healthbar_node = gui.get_node("healthbar") local size = gui.get_size(healthbar_node) size.x = size.x + 10 gui.set_size(healthbar_node, size) ``` ## Dynamically created nodes To create a new node with script in runtime you have two options. The first option is to create nodes from scratch by calling the `gui.new_[type]_node()` functions. Those return a reference to the new node that you can use to manipulate the node: ```lua -- Create a new box node local new_position = vmath.vector3(400, 300, 0) local new_size = vmath.vector3(450, 400, 0) local new_boxnode = gui.new_box_node(new_position, new_size) gui.set_color(new_boxnode, vmath.vector4(0.2, 0.26, 0.32, 1)) -- Create a new text node local new_textnode = gui.new_text_node(new_position, "Hello!") gui.set_font(new_textnode, "sourcesans") gui.set_color(new_textnode, vmath.vector4(0.69, 0.6, 0.8, 1.0)) ``` The alternative way to create new nodes is to clone an existing node with the `gui.clone()` function or a tree of nodes with the `gui.clone_tree()` function: ```lua -- clone the healthbar local healthbar_node = gui.get_node("healthbar") local healthbar_node_2 = gui.clone(healthbar_node) -- clone button node-tree local button = gui.get_node("my_button") local new_button_nodes = gui.clone_tree(button) -- get the new tree root local new_root = new_button_nodes["my_button"] -- move the root (and children) 300 to the right local root_position = gui.get_position(new_root) root_position.x = root_position.x + 300 gui.set_position(new_root, root_position) ``` ## Dynamic node Ids Dynamically created nodes do not have an id assigned to them. This is by design. The references that are returned from `gui.new_[type]_node()`, `gui.clone()` and `gui.clone_tree()` are the only thing necessary to be able to access the nodes and you should keep track of that reference. ```lua -- Add a text node local new_textnode = gui.new_text_node(vmath.vector3(100, 100, 0), "Hello!") -- "new_textnode" contains the reference to the node. -- The node has no id, and that is fine. There's no reason why we want -- to do gui.get_node() when we already have the reference. ``` # Clipping {#manuals:gui-clipping} GUI nodes can be used as *clipping* nodes---masks that control how other nodes are rendered. This manual explains how this feature works. ## Creating a clipping node Box, Text and Pie nodes can be used for clipping. To create a clipping node, add a node in your GUI, then set its properties accordingly: Clipping Mode : The mode used for clipping. - `None` renders the node without any clipping taking place. - `Stencil` makes the node writing to the current stencil mask. Clipping Visible : Check to render the content of the node. Clipping Inverted : Check to write the inversion of the node's shape to the mask. Then add the node(s) you want to be clipped as children to the clipping node. ## Stencil mask Clipping works by having nodes writing to a *stencil buffer*. This buffer contains clipping masks: information that that tells the graphics card whether a pixel should be rendered or not. - A node with no clipper parent but with clipping mode set to `Stencil` will write its shape (or its inverse shape) to an new clipping mask stored in the stencil buffer. - If a clipping node has a clipper parent it will instead clip the parent's clipping mask. A clipping child node can never _extend_ the current clipping mask, only clip it further. - Non clipper nodes that are children to clippers will be rendered with the clipping mask created by the parent hierarchy. Here, three nodes are set up in a hierarchy: - The hexagon and square shapes are both stencil clippers. - The hexagon creates a new clipping mask, the square clips it further. - The circle node is a regular pie node so it will be rendered with the clipping mask created by its parent clippers. Four combinations of normal and inverted clippers are possible for this hierarchy. The green area marks the part of the circle that is rendered. The rest is masked: ## Stencil limitations - The total number of stencil clippers can not exceed 256. - The maximum nesting depth of child _stencil_ nodes is 8 levels deep. (Only nodes with stencil clipping count.) - The maximum number of stencil node siblings is 127. For each level down a stencil hierarchy, the max limit is halved. - Inverted nodes have a higher cost. There is a limit to 8 inverted clipping nodes and each will halve the max amount of non-inverted clipping nodes. - Stencils render a stencil mask from the _geometry_ of the node (not the texture). It is possible to invert the mask by setting the *Inverted clipper* property. ## Layers Layers can be used to control rendering order (and batching) of nodes. When using layers and clipping nodes the usual layering order is overridden. Layer order always take precedence over the clipping order---if layer assignments are combined with clipping nodes, clipping could happen out-of-order if a parent node with clipping enabled belongs to a higher layer than its children. The children with no layer assigned will still respect the hierarchy and subsequently be drawn and clipped after the parent. A clipping node and its hierarchy will be drawn first if it has a layer assigned and in the regular order if no layer is assigned. In this example, both the clipper nodes "`Donut BG`" and "`BG`" are using the same layer 1. The render order between them will be according to the same order in the hierarchy where "`Donut BG`" is rendered before "`BG`". However, the child node "`Donut Shadow`" is assigned to the layer 2 which has a higher layer order and thus will be rendered after the both clipping nodes. In this case, the render order will be: - `Donut BG` - `BG` - `BG Frame` - `Donut Shadow` Here you can see that the "`Donut Shadow`" object will be clipped by both clipping nodes due to the layering, even though it is only a child to one of them. # Layouts {#manuals:gui-layouts} Defold supports GUIs that automatically adapt to screen orientation changes on mobile devices. By using this feature you can design GUIs that adapt to the orientation and aspect ratio of a range of screen sizes. It is also possible to create layouts that match particular device models. ## Creating display profiles By default, the *game.project* settings specify that a built-in display profiles settings file ("builtins/render/default.display_profiles") is used. The default profiles are "Landscape" (1280 pixels wide and 720 pixels high) and "Portrait" (720 pixels wide and 1280 pixels high). No device models are set on the profiles so they will match on any device. To create a new profiles settings file, either copy the one from the "builtins" folder or `right click` a suitable location in the *Assets* view and select `New... ▸ Display Profiles`. Give the new file a suitable name and click `Ok`. The editor now opens the new file for editing. Add new profiles by clicking the `+` in the *Profiles* list. For each profile, add a set of *qualifiers* for the profile: Width : The pixel width of the qualifier. Height : The pixel height of the qualifier. Device Models : A comma separated list of device models. The device model matches the start of the device model name, e.g. `iPhone10` will match "iPhone10,\*" models. Model names with commas should be enclosed in quotes, i.e. `"iPhone10,3", "iPhone10,6"` matches iPhone X models (see [iPhone wiki](https://www.theiphonewiki.com/wiki/Models)). Note that the only platforms reporting a device model when calling `sys.get_sys_info()` is Android and iOS. Other platforms return an empty string and will therefore never pick a display profile that has a device model qualifier. You also need to specify that the engine should use your new profiles. Open *game.project* and select the display profiles file in the *Display Profiles* setting under *display*: If you want the engine to automatically switch between portrait and landscape layouts on device rotation, check the *Dynamic Orientation* box. The engine will dynamically select a matching layout and also change the selection if the device changes orientation. ### Auto Layout Selection (Display Profiles) Display Profiles resource has an “Auto Layout Selection” option (ON by default). When ON, the engine automatically selects the best matching GUI layout both when the scene is created and when the window/display size changes. When OFF, the engine will not change layouts automatically—use `gui.set_layout()` from your GUI script to switch layouts manually. This setting is stored in the Display Profiles file and affects all GUI scene. ## GUI layouts The current set of display profiled can be used to create layout variants of your GUI node setup. To add a new layout to a GUI scene, right-click the *Layouts* icon in the *Outline* view and select `Add ▸ Layout ▸ ...`: When editing a GUI scene, all nodes are edited on a particular layout. The currently selected layout is indicated in the GUI scene layout dropdown in the toolbar. If no layout is chosen, the nodes are edited in the *Default* layout. Each change to a node property that you do with a layout selected _overrides_ the property in respect to the *Default* layout. Properties that are overridden are marked in blue. Nodes with overridden properties are also marked in blue. You can click on the reset button next to any overridden property to reset it to the original value. A layout cannot delete or create new nodes, only override properties. If you need to remove a node from a layout you can either move the node off-screen or delete it with script logic. You should also pay attention to the currently selected layout. If you add a layout to your project, the new layout will be set up according to the currently selected layout. Also, copying and pasting nodes considers the currently selected layout, when copying *and* when pasting. ## Dynamic profile selection When Auto Layout Selection is enabled, the engine automatically selects the best matching layout. The dynamic layout matching scores each display profile qualifier according to the following rules: 1. If there is no device model set, or the device model matches, a score (S) is calculated for the qualifier. 2. The score (S) is calculated with the area of the display (A), the area from the qualifier (A_Q), the aspect ratio of the display (R) and the aspect ratio of the qualifier (R_Q): 3. The profile with the lowest scoring qualifier is selected, if the orientation (landscape or portrait) of the qualifier matches the display. 4. If no profile with a qualifier of the same orientation is found, the profile with the best scoring qualifier of the other orientation is selected. 5. If no profile can be selected, the *Default* fallback profile is used. Since the *Default* layout is used as fallback in runtime if there are no better matching layout it means that if you add a "Landscape" layout, it will be the best match for *all* orientations until you also add a "Portrait" layout. ## Layout change messages When the layout changes, a `layout_changed` message is posted to the GUI component’s script. This happens when the engine changes layout automatically (Auto Layout Selection ON) or when your script calls `gui.set_layout()` and the layout actually changes. The message contains the hashed id of the layout so the script can perform logic depending on which layout is selected: ```lua function on_message(self, message_id, message, sender) if message_id == hash("layout_changed") and message.id == hash("My Landscape") then -- switching layout to landscape elseif message_id == hash("layout_changed") and message.id == hash("My Portrait") then -- switching layout to portrait end end ``` In addition, the current render script receives a message whenever the window (game view) changes and this includes orientation changes. ```lua function on_message(self, message_id, message) if message_id == hash("window_resized") then -- The window was resized. message.width and message.height contain the -- new dimensions of the window. end end ``` When orientation is switched, the GUI layout manager will automatically scale and reposition GUI nodes according to your layout and node properties. In-game content, however, is rendered in a separate pass (by default) with a stretch-fit projection into the current window. To change this behavior, either supply your own modified render script, or use a camera [library](https://defold.com/assets/). ## Manual layout selection (Lua) When Auto Layout Selection is OFF for the Display Profiles in use, the engine won’t switch layouts automatically. Use these functions from a GUI script to manage layouts manually: ### gui.set_layout(layout) - Accepts a string or hash (layout id). - Returns boolean: `true` if the layout exists in the scene and was applied; `false` otherwise. - If the layout exists in Display Profiles, updates the scene resolution to the profile’s width/height. - Emits `layout_changed` when the layout actually changes. Example: ```lua function init(self) -- Manually apply the "Portrait" layout local ok = gui.set_layout("Portrait") if not ok then print("Portrait layout not found in this scene") end end ``` ### gui.get_layouts() - Returns a table mapping each layout id hash to `vmath.vector3(width, height, 0)`. - For the default layout, returns the current scene resolution. Example: ```lua local layouts = gui.get_layouts() for id, size in pairs(layouts) do print(id, size.x, size.y) end ``` Note: If a GUI layout exists in the scene but is not present in Display Profiles, `gui.set_layout()` still applies the per-layout node overrides but does not change the scene resolution. # Physics {#manuals:physics} Defold includes a modified version of the [Box2D](http://www.box2d.org) physics engine (version 2.2.1) for 2D physics simulations and the Bullet physics engine (version 2.77) for 3D physics. It allows you to simulate Newtonian physics interactions between different types of _collision objects_. This manual explains how this works. The main concepts of the physics engines used in Defold are: * **Collision objects** - A collision object is a component you use to give a game object physical behaviour. A collision object has physical properties like weight, friction and shape. [Learn how to create a collision object](#manuals:physics-objects). * **Collision shapes** - A collision object can either use several primitive shapes or a single complex shape to define its spatial extension. [Learn how to add shapes to a collision object](#manuals:physics-shapes). * **Collision groups** - All collision objects must belong to a predefined group and each collision object can specify a list of other groups it can collide with. [Learn how to use collision groups](#manuals:physics-groups). * **Collision messages** - When two collision objects collide the physics engine send messages to the game objects the components belong to. [Learn more about collision messages](#manuals:physics-messages) In addition to the collision objects themselves you can also define collision object **constraints**, more commonly known as **joints**, to connect two collision objects and limit or in other ways apply force and influence how they behave in the physics simulation. [Learn more about joins](#manuals:physics-joints). You can also probe and read the physics world along a linear ray known as a **ray cast**. [Learn more about ray casts](#manuals:physics-ray-casts). ## Units used by the physics engine simulation The physics engine simulates Newtonian physics and it is designed to work well with meters, kilograms and seconds (MKS) units. Furthermore, the physics engine is tuned to work well with moving objects of a size in the 0.1 to 10 meters range (static objects can be larger) and by default the engine treats 1 unit (pixel) as 1 meter. This conversion between pixels and meters is convenient on a simulation level, but from a game creation perspective it isn't very useful. With default settings a collision shape with a size of 200 pixels would be treated as having a size of 200 meters which is well outside of the recommended range, at least for a moving object. In general it is required that the physics simulation is scaled for it to work well with the typical size of objects in a game. The scale of the physics simulation can be changed in *game.project* via the [physics scale setting](#manuals:project-settings). Setting this value to for instance 0.02 would mean that 200 pixels would be treated as a 4 meters. Do note that the gravity (also changed in *game.project*) has to be increased to accommodate for the change in scale. ## Physics updates It is recommended to update the physics engine at regular intervals to ensure a stable simulation (as opposed to updating at possibly irregular frame-rate dependent intervals). You can use a fixed update for physics by checking the [Use Fixed Timestep setting](#manuals:project-settings) of the Physics section in the *game.project* file. The update frequency is controlled by the [Fixed Update Frequency setting](#manuals:project-settings) of the Engine section in the *game.project* file. When using a fixed timestep for physics it is also recommended to use the `fixed_update(self, dt)` lifecycle function to interact with the collision objects of your game, for instance when applying forces to them. ## Caveats and common issues Collection proxies : Through collection proxies it is possible to load more than one top level collection, or *game world* into the engine. When doing so it is important to know that each top level collection is a separate physical world. Physics interactions ([collisions, triggers](#manuals:physics-messages) and [ray-casts](#manuals:physics-ray-casts)) only happen between objects belonging to the same world. So even if the collision objects from two worlds visually sits right on top of each other, there cannot be any physics interaction between them. Collisions not detected : If you have problems with collisions not being handled or detected properly then make sure to read up on [physics debugging in the Debugging manual](#manuals:debugging). # Collision shapes {#manuals:physics-shapes} A collision component can either use several primitive shapes or a single complex shape. ### Primitive shapes The primitive shapes are *box*, *sphere* and *capsule*. You add a primitive shape by `right clicking` the collision object and selecting `Add Shape`: ## Box shape A box has a position, rotation and dimensions (width, height and depth): ## Sphere shape A sphere has a position, rotation and diameter: ## Capsule shape A capsule has a position, rotation, diameter and height: Capsule shapes are only supported when using 3D physics (configured in the Physics section of the *game.project* file). ### Complex shapes A complex shape can either be created from a tilemap component or from a convex hull shape. ## Tilemap collision shape Defold includes a feature allowing you to easily generate physics shapes for the tile source used by a tile map. The [Tilesource manual](#manuals:tilesource) explains how to add collision groups to a tile source and assign tiles to collision groups ([example](https://defold.com/examples/tilemap/collisions/)). To add collision to a tile map: 1. Add the tilemap to a game object by `right-clicking` the game object and selecting `Add Component File`. Select the tile map file. 2. Add a collision object component to the game object by `right-clicking` the game object and selecting `Add Component ▸ Collision Object`. 3. Instead of adding shapes to the component, set the *Collision Shape* property to the *tilemap* file. 4. Set up the collision object component *Properties* as usual. Note that the *Group* property is **not** used here since the collision groups are defined in the tile map's tile source. ## Convex hull shape Defold includes a feature allowing you to create a convex hull shape from three or more points. 1. Create convex hull shape file (file extension `.convexshape`) using an external editor. 2. Edit the file manually using a text editor or external tool (see below) 3. Instead of adding shapes to the collision object component, set the *Collision Shape* property to the *convex shape* file. ### File Format The convex hull file format uses the same data format as all other Defold files, ie the protobuf text format. A convex hull shape defines the points of the hull. In 2D physics, the points should be provided in a counter clockwise order. An abstract point cloud is used in 3D physics mode. 2D example: ``` shape_type: TYPE_HULL data: 200.000 data: 100.000 data: 0.0 data: 400.000 data: 100.000 data: 0.0 data: 400.000 data: 300.000 data: 0.0 data: 200.000 data: 300.000 data: 0.0 ``` The above example defines the four corners of a rectangle: ``` 200x300 400x300 4---------3 | | | | | | | | 1---------2 200x100 400x100 ``` ## External tools There are a number of different external tools that can be used to create collision shapes: * The [Physics Editor](https://www.codeandweb.com/physicseditor/tutorials/how-to-create-physics-shapes-for-defold) from CodeAndWeb can be used to create game objects with sprites and matching collision shapes. * [Defold Polygon Editor](https://rossgrams.itch.io/defold-polygon-editor) can be used to create convex hull shapes. * [Physics Body Editor](https://selimanac.github.io/physics-body-editor/) can be used to create convex hull shapes. # Scaling collision shapes The collision object and its shapes inherit the scale of the game object. To disable this behaviour uncheck the [Allow Dynamic Transforms](#manuals:project-settings) checkbox in the Physics section of *game.project*. Note that only uniform scaling is supported and that the smallest scale value will be used if the scale isn't uniform. # Resizing collision shapes The shapes of a collision object can be resized at runtime using `physics.set_shape()`. Example: ```lua -- set capsule shape data local capsule_data = { type = physics.SHAPE_TYPE_CAPSULE, diameter = 10, height = 20, } physics.set_shape("#collisionobject", "my_capsule_shape", capsule_data) -- set sphere shape data local sphere_data = { type = physics.SHAPE_TYPE_SPHERE, diameter = 10, } physics.set_shape("#collisionobject", "my_sphere_shape", sphere_data) -- set box shape data local box_data = { type = physics.SHAPE_TYPE_BOX, dimensions = vmath.vector3(10, 10, 5), } physics.set_shape("#collisionobject", "my_box_shape", box_data) ``` A shape of the correct type with the specified id must already exist on the collision object. # Rotating collision shapes ## Rotating collision shapes in 3D physics Collision shapes in 3D physics can be rotated around all axis. ## Rotating collision shapes in 2D physics Collision shapes in 2D physics can only be rotated around the z-axis. Rotation around the x or y axis will yield incorrect results and should be avoided, even when rotating 180 degrees to essentially flip the shape along the x or y axis. To flip a physics shape it is recommended to use [`physics.set_hlip(url, flip)`](https://defold.com/ref/stable/physics/?#physics.set_hflip:url-flip) and [`physics.set_vlip(url, flip)`](https://defold.com/ref/stable/physics/?#physics.set_vflip:url-flip). # Debugging You can [enable Physics debugging](#manuals:debugging) to see the collision shapes at runtime. # Group and mask {#manuals:physics-groups} The physics engine allows you to group your physics objects and filter how they should collide. This is handled by named _collision groups_. For each collision object you create two properties control how the object collides with other objects, *Group* and *Mask*. For a collision between two objects to register both objects must mutually specify each other's groups in their *Mask* field. The *Mask* field can contain multiple group names, allowing for complex interaction scenarios. ## Detecting collisions When two collision objects with matching groups and masks collide the physics engine will generate [collision messages](#manuals:physics-messages) that can be used in games to react to collisions. # Collision messages {#manuals:physics-messages} When two objects collide, the engine will send an event to the event callback or broadcast messages to both objects. ## Event filtering The types of events generated may be controlled using the flags for each object: * "Generate Collision Events" * "Generate Contact Events" * "Generate Trigger Events" These are all `true` by default. When two collision objects interact, we check if we should send a message to the user, given these checkboxes. E.g. given the "Generate Contact Events" checkboxes: When using `physics.set_event_listener()`: | Component A | Component B | Send Message | |-------------|-------------|--------------| | ✅︎ | ✅︎ | Yes | | ❌ | ✅︎ | Yes | | ✅︎ | ❌ | Yes | | ❌ | ❌ | No | When using the default message handler: | Component A | Component B | Send Message(s) | |-------------|-------------|-------------------| | ✅︎ | ✅︎ | Yes (A,B) + (B,A) | | ❌ | ✅︎ | Yes (B,A) | | ✅︎ | ❌ | Yes (A,B) | | ❌ | ❌ | No | ## Collision response The `"collision_response"` message is sent when one of the colliding objects is of type "dynamic", "kinematic" or "static". It has the following fields set: `other_id` : the id of the instance the collision object collided with (`hash`) `other_position` : the world position of the instance the collision object collided with (`vector3`) `other_group` : the collision group of the other collision object (`hash`) `own_group` : the collision group of the collision object (`hash`) The collision_response message is only adequate to resolve collisions where you don't need any details on the actual intersection of the objects, for example if you want to detect if a bullet hits an enemy. There is only one of these messages sent for any colliding pair of objects each frame. ```Lua function on_message(self, message_id, message, sender) -- check for the message if message_id == hash("collision_response") then -- take action print("I collided with", message.other_id) end end ``` ## Contact point response The `"contact_point_response"` message is sent when one of the colliding objects is of type "dynamic" or "kinematic" and the other is of type "dynamic", "kinematic" or "static". It has the following fields set: `position` : world position of the contact point (`vector3`). `normal` : normal in world space of the contact point, which points from the other object towards the current object (`vector3`). `relative_velocity` : the relative velocity of the collision object as observed from the other object (`vector3`). `distance` : the penetration distance between the objects -- non negative (`number`). `applied_impulse` : the impulse the contact resulted in (`number`). `life_time` : (*not currently used!*) life time of the contact (`number`). `mass` : the mass of the current collision object in kg (`number`). `other_mass` : the mass of the other collision object in kg (`number`). `other_id` : the id of the instance the collision object is in contact with (`hash`). `other_position` : the world position of the other collision object (`vector3`). `other_group` : the collision group of the other collision object (`hash`). `own_group` : the collision group of the collision object (`hash`). For a game or application where you need to separate objects perfectly, the `"contact_point_response"` message gives you all information you need. However, note that for any given collision pair, several `"contact_point_response"` messages can be received each frame, depending on the nature of the collision. See [Resolving collisions for more information](#manuals:physics-resolving-collisions). ```Lua function on_message(self, message_id, message, sender) -- check for the message if message_id == hash("contact_point_response") then -- take action if message.other_mass > 10 then print("I collided with something weighing more than 10 kilos!") end end end ``` ## Trigger response The `"trigger_response"` message is sent when one of the colliding objects is of type "trigger". The message will be sent once when the collision is first detected and then once more when the objects are no longer colliding. It has the following fields: `other_id` : the id of the instance the collision object collided with (`hash`). `enter` : `true` if the interaction was an entry into the trigger, `false` if it was an exit. (`boolean`). `other_group` : the collision group of the other collision object (`hash`). `own_group` : the collision group of the collision object (`hash`). ```Lua function on_message(self, message_id, message, sender) -- check for the message if message_id == hash("trigger_response") then if message.enter then -- take action for entry print("I am now inside", message.other_id) else -- take action for exit print("I am now outside", message.other_id) end end end ``` # Defold Physics Event Handling {#manuals:physics-events} Previously, physics interactions in Defold were handled by broadcasting messages to all components of colliding objects. However, starting with version 1.6.4, Defold offers a more centralized approach through the `physics.set_event_listener()` function. This function allows you to set a custom listener to handle all physics interaction events in one place, thereby streamlining your code and improving efficiency. ## Setting the Physics World Listener In Defold, each collection proxy creates its own separate physics world. Therefore, when you are working with multiple collection proxies, it's essential to manage the distinct physics worlds associated with each. To ensure that physics events are handled correctly in each world, you must set a physics world listener specifically for each collection proxy's world. This setup means that the listener for physics events must be set from within the context of the collection that the proxy represents. By doing so, you associate the listener directly with the relevant physics world, enabling it to process physics events accurately. Here is an example of how to set a physics world listener within a collection proxy: ```lua function init(self) -- Assuming this script is attached to a game object within the collection loaded by the proxy -- Set the physics world listener for the physics world of this collection proxy physics.set_event_listener(physics_world_listener) end ``` By implementing this method, you ensure that each physics world generated by a collection proxy has its dedicated listener. This is crucial for handling physics events effectively in projects that utilize multiple collection proxies. If a listener is set, [physics messages](#manuals:physics-messages) will no longer be sent for the physics world where this listener is set. ## Event Data Structure Each physics event provides a `data` table containing specific information relevant to the event. 1. **Contact Point Event (`contact_point_event`):** This event reports a contact point between two collision objects. It is useful for detailed collision handling, such as calculating impact forces or custom collision responses. - `applied_impulse`: The impulse resulting from the contact. - `distance`: The penetration distance between the objects. - `a` and `b`: Objects representing the colliding entities, each containing: - `position`: World position of contact point (vector3). - `instance_position`: World position game object instance (vector3). - `id`: Instance ID (hash). - `group`: Collision group (hash). - `relative_velocity`: Velocity relative to the other object (vector3). - `mass`: Mass in kilograms (number). - `normal`: Contact normal, pointing from the other object (vector3). 2. **Collision Event (`collision_event`):** This event indicates that a collision has occurred between two objects. It is a more generalized event compared to the contact point event, ideal for detecting collisions without needing detailed information about the contact points. - `a` and `b`: Objects representing the colliding entities, each containing: - `position`: World position (vector3). - `id`: Instance ID (hash). - `group`: Collision group (hash). 3. **Trigger Event (`trigger_event`):** This event is sent when an object interacts with a trigger object. It's useful for creating areas in your game that cause something to happen when an object enters or exits. - `enter`: Indicates if the interaction was an entry (true) or an exit (false). - `a` and `b`: Objects involved in the trigger event, each containing: - `id`: Instance ID (hash). - `group`: Collision group (hash). 4. **Ray Cast Response (`ray_cast_response`):** This event is sent in response to a raycast, providing information about the object hit by the ray. - `group`: Collision group of the hit object (hash). - `request_id`: Identifier of the raycast request (number). - `position`: Hit position (vector3). - `fraction`: The fraction of the ray's length at which the hit occurred (number). - `normal`: Normal at the hit position (vector3). - `id`: Instance ID of the hit object (hash). 5. **Ray Cast Missed (`ray_cast_missed`):** This event is sent when a raycast does not hit any object. - `request_id`: Identifier of the raycast request that missed (number). ## Example Usage ```lua local function physics_world_listener(self, events) for _,event in ipairs(events) do if event.type == hash("contact_point_event") then -- Handle detailed contact point data pprint(event) elseif event.type == hash("collision_event") then -- Handle general collision data pprint(event) elseif event.type == hash("trigger_event") then -- Handle trigger interaction data pprint(event) elseif event.type == hash("ray_cast_response") then -- Handle raycast hit data pprint(event) elseif event.type == hash("ray_cast_missed") then -- Handle raycast miss data pprint(event) end end end function init(self) physics.set_event_listener(physics_world_listener) end ``` ## Limitations The listener calls synchronously at the moment it occurs. It happens in the middle of a timestep, which means that the physics world is locked. This makes it impossible to use functions that may affect physics world simulations, e.g., `physics.create_joint()`. Here is a small example of how to avoid these limitations: ```lua local function physics_world_listener(self, events) for _,event in ipairs(events) do if event.type == hash("contact_point_event") then local position_a = event.a.normal * SIZE local position_b = event.b.normal * SIZE local url_a = msg.url(nil, event.a.id, "collisionobject") local url_b = msg.url(nil, event.b.id, "collisionobject") -- fill the message in the same way arguments should be passed to `physics.create_joint()` local message = {physics.JOINT_TYPE_FIXED, url_a, "joind_id", position_a, url_b, position_b, {max_length = SIZE}} -- send message to the object itself msg.post(".", "create_joint", message) end end end function on_message(self, message_id, message) if message_id == hash("create_joint") then -- unpack message with function arguments physics.create_joint(unpack(message)) end end function init(self) physics.set_event_listener(physics_world_listener) end ``` # Resolving kinematic collisions {#manuals:physics-resolving-collisions} Using kinematic collision objects require you to resolve collisions yourself and move the objects as a reaction. A naive implementation of separating two colliding objects looks like this: ```lua function on_message(self, message_id, message, sender) -- Handle collision if message_id == hash("contact_point_response") then local newpos = go.get_position() + message.normal * message.distance go.set_position(newpos) end end ``` This code will separate your kinematic object from other physics object it penetrates, but the separation often overshoots and you will see jitter in many cases. To understand the problem better, consider the following case where a player character has collided with two objects, *A* and *B*: The physics engine will send multiple `"contact_point_response"` message, one for object *A* and one for object *B* the frame the collision occurs. If you move the character in response to each penetration, as in the naive code above, the resulting separation would be: - Move the character out of object *A* according to its penetration distance (the black arrow) - Move the character out of object *B* according to its penetration distance (the black arrow) The order of these is arbitrary but the result is the same either way: a total separation that is the *sum of the individual penetration vectors*: To properly separate the character from objects *A* and *B*, you need to handle each contact point's penetration distance and check if any previous separations have already, wholly or partially, solved the separation. Suppose that the first contact point message comes from object *A* and that you move the character out by *A*'s penetration vector: Then the character has already been partially separated from *B*. The final compensation necessary to perform full separation from object *B* is indicated by the black arrow above. The length of the compensation vector can be calculated by projecting the penetration vector of *A* onto the penetration vector of *B*: ``` l = vmath.project(A, B) * vmath.length(B) ``` The compensation vector can be found by reducing the length of *B* by *l*. To calculate this for an arbitrary number of penetrations, you can accumulate the necessary correction in a vector by, for each contact point, and starting with a zero length correction vector: 1. Project the current correction against the contact's penetration vector. 2. Calculate what compensation is left from the penetration vector (as per the formula above). 3. Move the object by the compensation vector. 4. Add the compensation to the accumulated correction. A complete implementation looks like this: ```lua function init(self) -- correction vector self.correction = vmath.vector3() end function update(self, dt) -- reset correction self.correction = vmath.vector3() end function on_message(self, message_id, message, sender) -- Handle collision if message_id == hash("contact_point_response") then -- Get the info needed to move out of collision. We might -- get several contact points back and have to calculate -- how to move out of all of them by accumulating a -- correction vector for this frame: if message.distance > 0 then -- First, project the accumulated correction onto -- the penetration vector local proj = vmath.project(self.correction, message.normal * message.distance) if proj < 1 then -- Only care for projections that does not overshoot. local comp = (message.distance - message.distance * proj) * message.normal -- Apply compensation go.set_position(go.get_position() + comp) -- Accumulate correction done self.correction = self.correction + comp end end end end ``` ## Ray casts {#manuals:physics-ray-casts} Ray casts are used to read the physics world along a linear ray. To cast a ray into the physics world, you provide a start and end position as well as [a set of collision groups](#manuals:physics-groups) to test against. If the ray hits a physics object you will get information about the object it hit. Rays intersect with dynamic, kinematic and static objects. They do not interact with triggers. ```lua function update(self, dt) -- request ray cast local my_start = vmath.vector3(0, 0, 0) local my_end = vmath.vector3(100, 1000, 1000) local my_groups = { hash("my_group1"), hash("my_group2") } local result = physics.raycast(my_start, my_end, my_groups) if result then -- act on the hit (see 'ray_cast_response' message for all values) print(result.id) end end ``` Ray casts will ignore collision objects that contain the starting point of the ray. This is a limitation in Box2D. # Joints {#manuals:physics-joints} Defold supports joints for 2D physics. A joint connects two collision objects using some kind of constraint. The supported joint types are: * **Fixed (physics.JOINT_TYPE_FIXED)** - A rope joint that restricts the maximum distance between two points. In Box2D referred to as a Rope joint. * **Hinge (physics.JOINT_TYPE_HINGE)** - A hinge joint specifies an anchor point on two collision objects and moves them so that the two collision objects are always in the same place, and the relative rotation of the collision objects is not restricted. The hinge joint can enable a motor with a defined maximum engine torque and speed. In Box2D referred to as a [Revolute joint](https://box2d.org/documentation/group__revolute__joint.html#details). * **Weld (physics.JOINT_TYPE_WELD)** - A weld joint attempts to constrain all relative movement between two collision objects. The weld joint can be made soft like a spring with a frequency and damping ratio. In Box2D referred to as a [Weld joint](https://box2d.org/documentation/group__weld__joint.html#details). * **Spring (physics.JOINT_TYPE_SPRING)** - A spring joint keeps two collision objects at a constant distance from each other. The spring joint can be made soft like a spring with a frequency and damping ratio. In Box2D referred to as a [Distance joint](https://box2d.org/documentation/group__distance__joint.html#details). * **Slider (physics.JOINT_TYPE_SLIDER)** - A slider joint allows for relative translation of two collision objects along a specified axis and prevents relative rotation. In Box2D referred to as a [Prismatic joint](https://box2d.org/documentation/group__prismatic__joint.html#details). * **Wheel (physics.JOINT_TYPE_WHEEL)** - A wheel joint restricts a point on `bodyB` to a line on `bodyA`. The wheel joint also provides a suspension spring. In Box2D referred to as a [Wheel joint](https://box2d.org/documentation/group__wheel__joint.html#details). ## Creating joints Joints can currently only be created programmatically using [`physics.create_joint()`](https://defold.com/ref/physics/#physics.create_joint:joint_type-collisionobject_a-joint_id-position_a-collisionobject_b-position_b-[properties]): Editor support for creating joints is planned but no release date has been decided. ```lua -- connect two collision objects with a fixed joint constraint (rope) physics.create_joint(physics.JOINT_TYPE_FIXED, "obj_a#collisionobject", "my_test_joint", vmath.vector3(10, 0, 0), "obj_b#collisionobject", vmath.vector3(0, 20, 0), { max_length = 20 }) ``` The above will create a fixed joint with id `my_test_joint` connected between the two collision object `obj_a#collisionobject` and `obj_b#collisionobject`. The joint is connected 10 pixels to the left of the center of collision object `obj_a#collisionobject` and 20 pixels above the center of collision object `obj_b#collisionobject`. The maximum length of the joint is 20 pixels. ## Destroying joints A joint can be destroyed using [`physics.destroy_joint()`](https://defold.com/ref/physics/#physics.destroy_joint:collisionobject-joint_id): ```lua -- destroy a joint previously connected to the first collision object physics.destroy_joint("obj_a#collisionobject", "my_test_joint") ``` ## Reading from and updating joints The properties of a joint can be read using [`physics.get_joint_properties()`](https://defold.com/ref/physics/#physics.get_joint_properties:collisionobject-joint_id) and set using [`physics.set_joint_properties()`](https://defold.com/ref/physics/#physics.set_joint_properties:collisionobject-joint_id-properties): ```lua function update(self, dt) if self.accelerating then local hinge_props = physics.get_joint_properties("obj_a#collisionobject", "my_hinge") -- increase motor speed by 100 revolutions per second hinge_props.motor_speed = hinge_props.motor_speed + 100 * 2 * math.pi * dt physics.set_joint_properties("obj_a#collisionobject", "my_hinge", hinge_props) end end ``` ## Get joint reaction force and torque The reaction force and torque applied to a joint can be read using [`physics.get_joint_reaction_force()`](https://defold.com/ref/physics/#physics.get_joint_reaction_force:collisionobject-joint_id) and [`physics.get_joint_reaction_torque()`](https://defold.com/ref/physics/#physics.get_joint_reaction_torque:collisionobject-joint_id). # Sound Streaming {#manuals:sound-streaming} While the default behaviour is to load sound data in full, it may also be beneficial to load the data in chunks, prior to their use. This is often called "streaming". One benefit of sound streaming is that less runtime memory is required, another is if you are streaming content from e.g. a http url, you can update the content at any time, and also avoid the initial download. ### Example There is an example project showcasing this setup: [https://github.com/defold/example-sound-streaming](https://github.com/defold/example-sound-streaming) ## How to enable streaming sounds ### Easy way The simplest way to use sound streaming, is by enabling the [`sound.stream_enabled` setting](#manuals:project-settings) in *game.project*. When this option is enabled the engine will start streaming the sounds. Note: If you have lots of sound files loaded at the same time, you may need to increase the `sound.stream_cache_size` value (see below). ### Runtime resources You can also create a new sound data resource, and set it to a sound component. You do this by: * Load the initial part of the sound file data * Note: This is the raw sound file, including the ogg/wav header * Create a new sound data resource by calling [`resource.create_sound_data()`](https://defold.com/ref/resource/#resource.create_sound_data). * Set the new sound data resource to the sound component using [`go.set()`](https://defold.com/ref/go#go.set) Here is an excerpt from the example project, using a `http.request()` to get the initial sound file. The web server you're loading content from has to support [HTTP range requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Range_requests). ```lua local function play_sound(self, hash) go.set(self.component, "sound", hash) -- override the resource data on the component sound.play(self.component) -- start playing the sound end local function parse_range(s) local _, _, rstart, rend, size = string.find(s, "(%d+)-(%d+)/(%d+)") -- "bytes 0-16383/103277" return rstart, rend, size end -- Callback for the http response. local function http_result(self, _id, response, extra) if response.status == 200 or response.status == 206 then -- Successful request local relative_path = self.filename local range = response.headers['content-range'] -- content-range = "bytes 0-16383/103277" local rstart, rend, filesize = parse_range(range) -- Create the Defold resource -- "partial" will enable the streaming mode print("Creating resource", relative_path) local hash = resource.create_sound_data(relative_path, { data = response.response, filesize = filesize, partial = true }) -- send "play_sound" to the component play_sound(self, hash) end end local function load_web_sound(base_url, relative_path) local url = base_url .. "/" .. relative_path local headers = {} headers['Range'] = string.format("bytes=%d-%d", 0, 16384-1) http.request(url, "GET", http_result, headers, nil, { ignore_cache = true }) end ``` ## Resource providers You can use other means to load the initial chunk of the sound file. The important thing to remember is that the rest of the chunks are loaded from the resource system and its resource providers. In this example, we add a new (http) file provider by adding a live update mount, by calling using [liveupdate.add_mount()](https://defold.com/ref/liveupdate/#liveupdate.add_mount). You can find a working example in [https://github.com/defold/example-sound-streaming](https://github.com/defold/example-sound-streaming). ```lua -- See http_result() from above example local function load_web_sound(base_url, relative_path) local url = base_url .. "/" .. relative_path local headers = {} -- Request the initial part of the file headers['Range'] = string.format("bytes=%d-%d", 0, 16384-1) http.request(url, "GET", http_result, headers, nil, { ignore_cache = true }) end function init(self) self.base_url = "http://my.server.com" self.filename = "/path/to/sound.ogg" liveupdate.add_mount("webmount", self.base_url, 100, function () -- once the mount is ready, we can start our request for downloading the first chunk load_web_sound(self.base_url, self.filename) end) end function final(self) liveupdate.remove_mount("webmount") end ``` ## Sound chunk cache The amount of memory consumed by the sounds at runtime is controlled by the [`sound.stream_cache_size` setting](#manuals:project-settings) in *game.project*. Given this limit, the loaded sound data will never exceed this limit. The initial chunk of each sound file cannot be evicted and they will occupy the cache for as long as the resources are loaded. The size of the initial chunk is controlled by the [`sound.stream_preload_size` setting](#manuals:project-settings) in *game.project*. You can also control the size of each sound chunk by changing the [`sound.stream_chunk_size` setting](#manuals:project-settings) in *game.project*. This may help you get the sound cache size down even further if you have many sound files loaded at the same time. Sound files smaller than the sound chunk size, aren't streamed and if a new chunk doesn't fit into the cache, the oldest chunk is evicted The total size of the sound chunk cache should be larger than the number of loaded sound files times the stream chunk size. Otherwise, you risk evicting new chunks each frame and sounds won't play properly # Input {#manuals:input} All user input is captured by the engine and dispatched as actions to script- and GUI script components in game objects that have acquired input focus and that implement the `on_input()` function. This manual explains how you set up bindings to capture input and how you create code that responds to it. The input system uses a set of simple and powerful concepts, allowing you to manage input as you see fit for your game. Devices : Input devices that are either part of, or plugged into, your computer or mobile device provide raw system level input to the Defold runtime. The following device types are supported: 1. Keyboard (single key as well as text input) 2. Mouse (position, button clicks and mouse wheel actions) 3. Single and multi-touch (on iOS and Android devices and HTML5 on mobile) 4. Gamepads (as supported through the operating system and mapped in the [gamepads](#gamepads-settings-file) file) Input bindings : Before input is sent to a script the raw input from the device is translated into meaningful *actions* via the input bindings table. Actions : Actions are identified by the (hashed) names that you list in the input bindings file. Each action also contain relevant data about the input: if a button is pressed or released, the coordinates of the mouse and touch etc. Input listeners : Any script component or GUI script can receive input actions by *acquiring input focus*. Several listeners can be active at the same time. Input stack : The list of input listeners with the first acquirer of focus at the bottom of the stack and the last acquirer at the top. Consuming input : A script may choose to consume the input it received, preventing listeners further down the stack to receive it. ## Setting up input bindings The input bindings is a project wide table that allows you to specify how device input should translate into named *actions* before they are dispatched to your script components and GUI scripts. You can create a new input binding file, `right click` a location in the *Assets* view and select `New... ▸ Input Binding`. To make the engine use the new file, change the *Game Binding* entry in *game.project*. A default input binding file is automatically created with all new project templates so there is usually no need to create a new binding file. The default file is called "game.input_binding" and can be found in the "input" folder in the project root. `Double click` the file to open it in the editor: To create a new binding, click the `+` button at the bottom of the relevant trigger type section. Each entry has two fields: *Input* : The raw input to listen for, selected from a scroll list of available inputs. *Action* : The action name given to input actions when they are created and dispatched to your scripts. The same action name can be assigned to multiple inputs. For instance, you can bind the `Space` key and the gamepad "A" button to the action `jump`. Note that there is a known bug where touch inputs unfortunately cannot have the same action names as other inputs. ## Trigger types There are five device specific types of triggers that you can create: Key Triggers : Single key keyboard input. Each key is mapped separately into a corresponding action. Learn more in the [key and text input manual](#manuals:input-key-and-text). Text Triggers : Text triggers are used to read arbitrary text input. Learn more in the [key and text input manual](#manuals:input-key-and-text) Mouse Triggers : Input from mouse buttons and scroll wheels. Learn more in the [mouse and touch input manual](#manuals:input-mouse-and-touch). Touch Triggers : Single-touch and Multi-touch type triggers are available on iOS and Android devices in native applications and in HTML5 bundles. Learn more in the [mouse and touch manual](#manuals:input-mouse-and-touch). Gamepad Triggers : Gamepad triggers allow you to bind standard gamepad input to game functions. Learn more in the [gamepads manual](#manuals:input-gamepads). ### Accelerometer input In addition to the five different trigger types listed above Defold also supports accelerometer input in native Android and iOS applications. Check the Use Accelerometer box in the Input section of your *game.project* file. ```lua function on_input(self, action_id, action) if action.acc_x and action.acc_y and action.acc_z then -- react to accelerometer data end end ``` ## Input focus To listen to input actions in a script component or GUI script, the message `acquire_input_focus` should be sent to the game object holding the component: ```lua -- tell the current game object (".") to acquire input focus msg.post(".", "acquire_input_focus") ``` This message instructs the engine to add input capable components (script components, GUI components and collection proxies) in the game objects to the *input stack*. The game object components are put on top of the input stack; the component that is added last will be top of the stack. Note that if the game object contains more than one input capable component, all components will be added to the stack: If a game object that has already acquired input focus does so again, its component(s) will be moved to the top of the stack. ## Input dispatch and on_input() Input actions are dispatched according to the input stack, from the top to the bottom. Any component that is on the stack containing an `on_input()` function will have that function called, once for each input action during the frame, with the following arguments: `self` : The current script instance. `action_id` : The hashed name of the action, as set up in the input bindings. `action` : A table containing the useful data about the action, like the value of the input, its location (absolute and delta positions), whether button input was `pressed` etc. See [on_input()](https://defold.com/ref/go#on_input) for details on the available action fields. ```lua function on_input(self, action_id, action) if action_id == hash("left") and action.pressed then -- move left local pos = go.get_position() pos.x = pos.x - 100 go.set_position(pos) elseif action_id == hash("right") and action.pressed then -- move right local pos = go.get_position() pos.x = pos.x + 100 go.set_position(pos) end end ``` ### Input focus and collection proxy components Each game world that is dynamically loaded through a collection proxy has its own input stack. For action dispatch to reach the loaded world's input stack, the proxy component must be on the main world's input stack. All components on a loaded world's stack are handled before dispatch continues down the main stack: It is a common error to forget to send `acquire_input_focus` to the game object holding the collection proxy component. Skipping this step prevents input from reaching any of the components on the loaded world's input stack. ### Releasing input To stop listening to input actions, send a `release_input_focus` message to the game object. This message will remove any of the game object's components from the input stack: ```lua -- tell the current game object (".") to release input focus. msg.post(".", "release_input_focus") ``` ## Consuming input A component's `on_input()` can actively control whether actions should be passed on further down the stack or not: - If `on_input()` returns `false`, or a return is omitted (this implies a `nil` return which is a false value in Lua) input actions will be passed on to the next component on the input stack. - If `on_input()` returns `true` input is consumed. No component further down the input stack will receive the input. Note that this applies to *all* input stacks. A component on a proxy-loaded world's stack can consume input preventing components on the main stack to receive input: There are many good use cases where input consumption provides a simple and powerful way to shift input between different parts of a game. For example, if you need a pop-up menu that temporarily is the only part of the game that listens to input: The pause menu is initially hidden (disabled) and when the player touches the "PAUSE" HUD item, it is enabled: ```lua function on_input(self, action_id, action) if action_id == hash("mouse_press") and action.pressed then -- Did the player press PAUSE? local pausenode = gui.get_node("pause") if gui.pick_node(pausenode, action.x, action.y) then -- Tell the pause menu to take over. msg.post("pause_menu", "show") end end end ``` The pause menu GUI acquires input focus and consumes input, preventing any input other than what's relevant for the pop-up menu: ```lua function on_message(self, message_id, message, sender) if message_id == hash("show") then -- Show the pause menu. local node = gui.get_node("pause_menu") gui.set_enabled(node, true) -- Acquire input. msg.post(".", "acquire_input_focus") end end function on_input(self, action_id, action) if action_id == hash("mouse_press") and action.pressed then -- do things... local resumenode = gui.get_node("resume") if gui.pick_node(resumenode, action.x, action.y) then -- Hide the pause menu local node = gui.get_node("pause_menu") gui.set_enabled(node, false) -- Release input. msg.post(".", "release_input_focus") end end -- Consume all input. Anything below us on the input stack -- will never see input until we release input focus. return true end ``` It is recommended that you familiarize yourself with the general way in which input works in Defold, how to receive input and in which order input is received in your script files. Learn more about the input system in the [Input Overview manual](#manuals:input). # Key Triggers Key triggers allow you to bind single key keyboard input to game actions. Each key is mapped separately into a corresponding action. Key triggers are used to tie specific buttons to specific functions, like character movement with the arrow or WASD keys. If you need to read arbitrary keyboard input, use text triggers (see below). ```lua function on_input(self, action_id, action) if action_id == hash("left") then if action.pressed then -- start moving left elseif action.released then -- stop moving left end end end ``` # Text Triggers Text triggers are used to read arbitrary text input. There are two types of text triggers; text and marked text. ## Text The `text` captures normal text input. It sets the `text` field of the action table to a string containing the typed character. The action is only fired at the press of the button, no `release` or `repeated` action is sent. ```lua function on_input(self, action_id, action) if action_id == hash("text") then -- Concatenate the typed character to the "user" node... local node = gui.get_node("user") local name = gui.get_text(node) name = name .. action.text gui.set_text(node, name) end end ``` ## Marked text The `marked-text` is used primarily for Asian keyboards where multiple keypresses can map to single inputs. For example, with the iOS "Japanese-Kana" keyboard, the user can type combinations and the top of the keyboard will display available symbols or sequences of symbols that can be entered. - Each keypress generates a separate action and sets the action field `text` to the currently entered sequence of symbols (the "marked text"). - When the user selects a symbol or symbol combination, a separate `text` type trigger action is sent (provided that one is set up in the input binding list). The separate action sets the action field `text` to the final sequence of symbols. It is recommended that you familiarize yourself with the general way in which input works in Defold, how to receive input and in which order input is received in your script files. Learn more about the input system in the [Input Overview manual](#manuals:input). # Mouse Triggers Mouse triggers allow you to bind input from mouse buttons and scroll wheels to game actions. Mouse button inputs `MOUSE_BUTTON_LEFT`, `MOUSE_BUTTON_RIGHT` and `MOUSE_BUTTON_MIDDLE` are equivalent to `MOUSE_BUTTON_1`, `MOUSE_BUTTON_2` and `MOUSE_BUTTON_3`. The examples below use the actions shown in the image above. As with all input you are free to name your input actions any way you want to. ## Mouse buttons Mouse buttons generate pressed, released and repeated events. Example showing how to detect input for the left mouse button (either pressed or released): ```lua function on_input(self, action_id, action) if action_id == hash("mouse_button_left") then if action.pressed then -- left mouse button pressed elseif action.released then -- left mouse button released end end end ``` `MOUSE_BUTTON_LEFT` (or `MOUSE_BUTTON_1`) input actions are sent for single touch inputs as well. ## Mouse wheel Mouse wheel inputs detect scroll actions. The field `action.value` is `1` if the wheel is scrolled and `0` otherwise. (Scroll actions are dealt with as they were button presses. Defold does not currently support fine grained scroll input on touch pads.) ```lua function on_input(self, action_id, action) if action_id == hash("mouse_wheel_up") then if action.value == 1 then -- mouse wheel is scrolled up end end end ``` ## Mouse movement Mouse movement is handled separately. Mouse movement events are not received unless at least one mouse trigger is set up in your input bindings. Mouse movement are not bound in the input bindings but `action_id` is set to `nil` and the `action` table is populated with the location and delta movement of the mouse position. ```lua function on_input(self, action_id, action) if action.x and action.y then -- let game object follow mouse/touch movement local pos = vmath.vector3(action.x, action.y, 0) go.set_position(pos) end end ``` # Touch Triggers Single-touch and Multi-touch type triggers are available on iOS and Android devices in native applications and in HTML5 bundles. ## Single-touch Single-touch type triggers are not set up from the Touch Triggers section of the input bindings. Instead **single-touch triggers are automatically set up when you have mouse button input set up for `MOUSE_BUTTON_LEFT` or `MOUSE_BUTTON_1`**. ## Multi-touch Multi-touch type triggers populate a table in the action table called `touch`. The elements in the table are integer-indexed with numbers `1`--`N`where `N` is the number of touch points. Each element of the table contains fields with input data: ```lua function on_input(self, action_id, action) if action_id == hash("touch_multi") then -- Spawn at each touch point for i, touchdata in ipairs(action.touch) do local pos = vmath.vector3(touchdata.x, touchdata.y, 0) factory.create("#factory", pos) end end end ``` Multi-touch must not be assigned the same action as the mouse button input for `MOUSE_BUTTON_LEFT` or `MOUSE_BUTTON_1`. Assigning the same action will effectively override single-touch and prevent you from receiving any single-touch events. The [Defold-Input asset](https://defold.com/assets/defoldinput/) can be used to easily set up virtual on-screen controls such as buttons and analog sticks with support for multi touch. ## Detecting click or tap on objects Detecting when the user has clicked or tapped on a visual component is a very common operation that is needed in many games. It could be user interaction with a button or other UI element or the interaction with a game object such as a player controlled unit in a strategy game, some treasure on a level in a dungeon crawler or a quest giver in an RPG. The approach to use varies depending on the type of visual component. ### Detecting interaction with GUI nodes For UI elements there is the `gui.pick_node(node, x, y)` function that will return true or false depending on if the specified coordinate is within the bounds of a gui node or not. Refer to the [API docs](https://defold.com/ref/gui/#gui.pick_node:node-x-y), the [pointer over example](https://defold.com/examples/gui/pointer_over/) or the [button example](https://defold.com/examples/gui/button/) to learn more. ### Detecting interaction with game objects For game objects it is more complicated to detect interaction since things such as camera translation and render script projection will impact the required calculations. There are two general approaches to detecting interaction with game objects: 1. Track the position and size of game objects the user can interact with and check if the mouse or touch coordinate is within the bounds of any of the objects. 2. Attach collision objects to game objects the user can interact with and one collision object that follows the mouse or finger and check for collisions between them. A ready to use solution for using collision objects to detect user input with drag and click support can be found in the [Defold-Input asset](https://defold.com/assets/defoldinput/). In both cases there is a need to convert from the screen space coordinates of the mouse or touch event and the world space coordinates of the game objects. This can be done in a couple of different ways: * Manually keep track of which view and projection that is used by the render script and use this to convert to and from world space. See the [camera manual for an example of this](#manuals:camera). * Use a [third-party camera solution](#manuals:camera) and make use of the provided screen-to-world conversion functions. It is recommended that you familiarize yourself with the general way in which input works in Defold, how to receive input and in which order input is received in your script files. Learn more about the input system in the [Input Overview manual](#manuals:input). # Gamepads Gamepad triggers allow you to bind standard gamepad input to game functions. Gamepad input offers bindings for: - Left and right sticks (direction and clicks) - Left and right digital pads. Right pad usually translates to the "A", "B", "X" and "Y" buttons on the Xbox controller and "square", "circle", "triangle" and "cross" buttons on the Playstation controller. - Left and right triggers - Left and right shoulder buttons - Start, Back and Guide buttons The examples below use the actions shown in the image above. As with all input you are free to name your input actions any way you want to. ## Digital buttons Digital buttons generate pressed, released and repeated events. Example showing how to detect input for a digital button (either pressed or released): ```lua function on_input(self, action_id, action) if action_id == hash("gamepad_lpad_left") then if action.pressed then -- start moving left elseif action.released then -- stop moving left end end end ``` ## Analog sticks Analog sticks generate continuous input events when the stick is moved outside the dead zone defined in the gamepad settings file (see below). Example showing how to detect input for an analog stick: ```lua function on_input(self, action_id, action) if action_id == hash("gamepad_lstick_down") then -- left stick was moved down print(action.value) -- a value between 0.0 an -1.0 end end ``` Analog sticks also generate pressed and released events when moved in the cardinal directions above a certain threshold value. This makes it easy to also use an analog stick as digital directional input: ```lua function on_input(self, action_id, action) if action_id == hash("gamepad_lstick_down") and action.pressed then -- left stick was moved to its extreme down position end end ``` ## Multiple gamepads Defold supports multiple gamepads through the host operating system, actions set the `gamepad` field of the action table to the gamepad number the input originated from: ```lua function on_input(self, action_id, action) if action_id == hash("gamepad_start") then if action.gamepad == 0 then -- gamepad 0 wants to join the game end end end ``` ## Connect and Disconnect Gamepad input bindings also provide two separate bindings named `Connected` and `Disconnected` to detect when a gamepad is connected (even those connected from the start) or disconnected. ```lua function on_input(self, action_id, action) if action_id == hash("gamepad_connected") then if action.gamepad == 0 then -- gamepad 0 was connected end elseif action_id == hash("gamepad_disconnected") then if action.gamepad == 0 then -- gamepad 0 was disconnected end end end ``` ## Raw gamepads (From Defold 1.2.183) Gamepad input bindings also provide a separate binding named `Raw` to give the unfiltered (without applied deadzone) button, axis and hat input of any connected gamepad. ```lua function on_input(self, action_id, action) if action_id == hash("raw") then pprint(action.gamepad_buttons) pprint(action.gamepad_axis) pprint(action.gamepad_hats) end end ``` ## Gamepads settings file Gamepad input setup uses a separate mapping file for each hardware gamepad type. Gamepad mappings for specific hardware gamepads are set in a *gamepads* file. Defold ships with a built-in gamepads file with settings for common gamepads: If you need to create a new gamepad settings file, we have a simple tool to help: [Click to download gdc.zip](https://forum.defold.com/t/big-thread-of-gamepad-testing/56032). It includes binaries for Windows, Linux and macOS. Run it from the command line: ```sh ./gdc ``` The tool will ask you to press different buttons on your connected controller. It will then output a new gamepads file with correct mappings for your controller. Save the new file, or merge it with your existing gamepads file, then update the setting in *game.project*: ### Unidentified gamepads (From Defold 1.2.186) When a gamepad is connected and no mapping exists for the gamepad the gamepad will only generate "connected", "disconnected" and "raw" actions. In this case you need to manually map the raw gamepad data to actions in your game. (From Defold 1.4.8) It is possible to check if an input action for a gamepad is from an unknown gamepad or not by reading the `gamepad_unknown` value from the action: ```lua function on_input(self, action_id, action) if action_id == hash("connected") then if action.gamepad_unknown then print("The connected gamepad is unidentified and will only generate raw input") else print("The connected gamepad is known and will generate input actions for buttons and sticks") end end end ``` ## Gamepads in HTML5 Gamepads are supported in HTML5 builds and generate the same input events as on other platforms. Support for gamepads is based on the [Gamepad API](https://www.w3.org/TR/gamepad/) which is supported in most browsers ([refer to this support chart](https://caniuse.com/?search=gamepad)). If the browser doesn't support the Gamepad API Defold will silently ignore any Gamepad triggers in your project. You can check if the browser supports the Gamepad API by checking if the `getGamepads` function exists on the `navigator` object: ```lua local function supports_gamepads() return not html5 or (html5.run('typeof navigator.getGamepads === "function"') == "true") end if supports_gamepads() then print("Platform supports gamepads") end ``` If your game is running from inside an `iframe` you must also make sure that the `iframe` has the `gamepad` permission added: ```html ``` ### Standard gamepad (From Defold 1.4.1) If a connected gamepad is identified by the browser as a standard gamepad it will use the mapping for "Standard Gamepad" in the [gamepads settings file](#manuals:input-gamepads) (a Standard Gamepad mapping is included in the `default.gamepads` file in `/builtins`). A standard gamepad is defined as having 16 buttons and 2 analog sticks with a button layout similar to a PlayStation or Xbox controller (see the [W3C definition and button layout](https://w3c.github.io/gamepad/#dfn-standard-gamepad) for more information). If the connected gamepad is not identified as a standard gamepad Defold will look for a mapping matching the hardware gamepad type in the gamepad settings file. ## Gamepads on Windows On Windows, only XBox 360 controllers are currently supported. To hook up your 360 controller to your Windows machine, [make sure it is setup correctly](http://www.wikihow.com/Use-Your-Xbox-360-Controller-for-Windows). ## Gamepads on Android (From Defold 1.2.183) Gamepads are supported in Android builds and generate the same input events as on other platforms. Support for gamepads is based on the [Android input system for key and motion events](https://developer.android.com/training/game-controllers/controller-input). The Android input events will be translated to Defold gamepad events using the same *gamepad* file as described above. When adding additional gamepad bindings on Android you can use the following lookup tables to translate from the Android input events to *gamepad* file values: | Key event to button index | Index | Version | |-----------------------------|-------|---------| | `AKEYCODE_BUTTON_A` | 0 | 1.2.183 | | `AKEYCODE_BUTTON_B` | 1 | 1.2.183 | | `AKEYCODE_BUTTON_C` | 2 | 1.2.183 | | `AKEYCODE_BUTTON_X` | 3 | 1.2.183 | | `AKEYCODE_BUTTON_L1` | 4 | 1.2.183 | | `AKEYCODE_BUTTON_R1` | 5 | 1.2.183 | | `AKEYCODE_BUTTON_Y` | 6 | 1.2.183 | | `AKEYCODE_BUTTON_Z` | 7 | 1.2.183 | | `AKEYCODE_BUTTON_L2` | 8 | 1.2.183 | | `AKEYCODE_BUTTON_R2` | 9 | 1.2.183 | | `AKEYCODE_DPAD_CENTER` | 10 | 1.2.183 | | `AKEYCODE_DPAD_DOWN` | 11 | 1.2.183 | | `AKEYCODE_DPAD_LEFT` | 12 | 1.2.183 | | `AKEYCODE_DPAD_RIGHT` | 13 | 1.2.183 | | `AKEYCODE_DPAD_UP` | 14 | 1.2.183 | | `AKEYCODE_BUTTON_START` | 15 | 1.2.183 | | `AKEYCODE_BUTTON_SELECT` | 16 | 1.2.183 | | `AKEYCODE_BUTTON_THUMBL` | 17 | 1.2.183 | | `AKEYCODE_BUTTON_THUMBR` | 18 | 1.2.183 | | `AKEYCODE_BUTTON_MODE` | 19 | 1.2.183 | | `AKEYCODE_BUTTON_1` | 20 | 1.2.186 | | `AKEYCODE_BUTTON_2` | 21 | 1.2.186 | | `AKEYCODE_BUTTON_3` | 22 | 1.2.186 | | `AKEYCODE_BUTTON_4` | 23 | 1.2.186 | | `AKEYCODE_BUTTON_5` | 24 | 1.2.186 | | `AKEYCODE_BUTTON_6` | 25 | 1.2.186 | | `AKEYCODE_BUTTON_7` | 26 | 1.2.186 | | `AKEYCODE_BUTTON_8` | 27 | 1.2.186 | | `AKEYCODE_BUTTON_9` | 28 | 1.2.186 | | `AKEYCODE_BUTTON_10` | 29 | 1.2.186 | | `AKEYCODE_BUTTON_11` | 30 | 1.2.186 | | `AKEYCODE_BUTTON_12` | 31 | 1.2.186 | | `AKEYCODE_BUTTON_13` | 32 | 1.2.186 | | `AKEYCODE_BUTTON_14` | 33 | 1.2.186 | | `AKEYCODE_BUTTON_15` | 34 | 1.2.186 | | `AKEYCODE_BUTTON_16` | 35 | 1.2.186 | ([Android `KeyEvent` definitions](https://developer.android.com/ndk/reference/group/input#group___input_1gafccd240f973cf154952fb917c9209719)) | Motion event to axis index | Index | |-----------------------------|-------| | `AMOTION_EVENT_AXIS_X` | 0 | | `AMOTION_EVENT_AXIS_Y` | 1 | | `AMOTION_EVENT_AXIS_Z` | 2 | | `AMOTION_EVENT_AXIS_RZ` | 3 | | `AMOTION_EVENT_AXIS_LTRIGGER` | 4 | | `AMOTION_EVENT_AXIS_RTRIGGER` | 5 | | `AMOTION_EVENT_AXIS_HAT_X` | 6 | | `AMOTION_EVENT_AXIS_HAT_Y` | 7 | ([Android `MotionEvent` definitions](https://developer.android.com/ndk/reference/group/input#group___input_1ga157d5577a5b2f5986037d0d09c7dc77d)) Use this lookup table in combination with a gamepad test app from the Google Play Store to figure out which key event each button on your gamepad is mapped to. # Scripts {#manuals:script} Script components allows you to create game logic using the [Lua programming language](#manuals:lua). ## Script types There are three types of Lua script in Defold, each has different Defold libraries available. Game Object scripts : Extension _.script_. These scripts are added to game objects exactly like any other [component](#manuals:components) and Defold will execute the Lua code as part of the engine lifecycle functions. Game Object scripts are usually used to control game objects and the logic that binds the game together with level loading, game rules and so forth. Game Object scripts have access to the [GO](https://defold.com/ref/go) functions and all Defold library functions except the [GUI](https://defold.com/ref/gui) and [Render](https://defold.com/ref/render) functions. GUI scripts : Extension _.gui_script_. Run by GUI components and usually containing the logic required to display GUI elements like heads up displays, menus etc. Defold will execute the Lua code as part of the engine lifecycle functions. GUI scripts have access to the [GUI](https://defold.com/ref/gui) functions and all Defold library functions except the [GO](https://defold.com/ref/go) and [Render](https://defold.com/ref/render) functions. Render scripts : Extension _.render_script_. Run by the rendering pipeline and containing the logic required to render all app/game graphics each frame. The render script has a special place in the lifecycle of your game. Details can be found in the [Application lifecycle documentation](#manuals:application-lifecycle). Render scripts have access to the [Render](https://defold.com/ref/render) functions and all Defold library functions except the [GO](https://defold.com/ref/go) and [GUI](https://defold.com/ref/gui) functions. ## Script execution, callbacks and self Defold executes Lua scripts as part of the engine lifecycle and exposes the lifecycle through a set of predefined callback functions. When you add a script component to a game object the script becomes part of the game object's and its component(s) lifecycle. The script is evaluated in the Lua context when it is loaded, then the engine executes the following functions and passes a reference to the current script component instance as parameter. You can use this `self` reference to store state in the component instance. `self` is a userdata object that acts like a Lua table but you can't iterate over it with `pairs()` or `ipairs()` and you can't print it using `pprint()`. #### `init(self)` Called when the component is initialized. ```lua function init(self) -- These variables are available through the lifetime of the component instance self.my_var = "something" self.age = 0 end ``` #### `final(self)` Called when the component is deleted. This is useful for cleaning up purposes, for instance if you have spawned game objects that should be deleted when the component is deleted. ```lua function final(self) if self.my_var == "something" then -- do some cleanup end end ``` #### `fixed_update(self, dt)` Frame-rate independent update. Parameter `dt` contains the delta time since the last update. This function is called `0-N` times depending on a frame timing and the fixed update frequency. It is called only when `Physics`-->`Use Fixed Timestep` is enabled, and `Engine`-->`Fixed Update Frequency` is larger than 0 in *game.project*. Useful when you wish to manipulate physics objects at regular intervals to achieve a stable physics simulation. ```lua function fixed_update(self, dt) msg.post("#co", "apply_force", {force = vmath.vector3(1, 0, 0), position = go.get_world_position()}) end ``` #### `update(self, dt)` Called once each frame after `fixed_update` callback of all scripts (if Fixed Timestep is enabled). Parameter `dt` contains the delta time since the last frame. ```lua function update(self, dt) self.age = self.age + dt -- increase age with the timestep end ``` #### `late_update(self, dt)` Called once each frame after `update` callback of all scripts, but just before render. Parameter `dt` contains the delta time since the last frame. ```lua function late_update(self, dt) go.set_position("/camera", self.final_camera_position) end ``` #### on_message(self, message_id, message, sender) When messages are sent to the script component through [`msg.post()`](https://defold.com/ref/msg#msg.post) the engine calls this function of the receiver component. Learn [more about message passing](#manuals:message-passing). ```lua function on_message(self, message_id, message, sender) if message_id == hash("increase_score") then self.total_score = self.total_score + message.score end end ``` #### `on_input(self, action_id, action)` If this component has acquired input focus (see [`acquire_input_focus`](https://defold.com/ref/go/#acquire_input_focus)) the engine calls this function when input is registered. Learn [more about input handling](#manuals:input). ```lua function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed then print("Touch", action.x, action.y) end end ``` #### `on_reload(self)` This function is called when the script is reloaded through the hot reload editor function (`Edit ▸ Reload Resource`). It is very useful for debugging, testing and tweaking purposes. Learn [more about hot-reload](#manuals:hot-reload). ```lua function on_reload(self) print(self.age) -- print the age of this game object end ``` ## Reactive logic A game object with a script component implements some logic. Often, that logic is dependent on some external factor. An enemy AI might react to the player being within a certain radius from the AI; a door might unlock and open as a result of player interaction, etc, etc. The `update()` function allows you to implement complex behaviors defined as a state machine running each frame---sometimes that is the adequate approach. But there is a cost associated with each call to `update()`. Unless you really need the function you should delete it and instead try to build your logic _reactively_. It is cheaper to passively wait for some message to trigger a response than it is to actively probe the game world for data to respond to. Furthermore, solving a design problem reactively also often leads to cleaner and more stable design and implementation. Let's look at a concrete example. Suppose that you want a script component to send a message 2 seconds after it has been initiated. It should then wait for a certain response message and after receiving the response, it should send another message 5 seconds later. The non reactive code for that would look something like this: ```lua function init(self) -- Counter to keep track of time. self.counter = 0 -- We need this to keep track of our state. self.state = "first" end function update(self, dt) self.counter = self.counter + dt if self.counter >= 2.0 and self.state == "first" then -- send message after 2 seconds msg.post("some_object", "some_message") self.state = "waiting" end if self.counter >= 5.0 and self.state == "second" then -- send message 5 seconds after we received "response" msg.post("another_object", "another_message") -- Nil the state so we don’t reach this state block again. self.state = nil end end function on_message(self, message_id, message, sender) if message_id == hash("response") then -- “first” state done. enter next self.state = "second" -- zero the counter self.counter = 0 end end ``` Even in this quite simple case we get fairly tangled up logic. It's possible to make this look better with the help of coroutines in a module (see below), but let's instead try to make this reactive and use a built-in timing mechanism. ```lua local function send_first() msg.post("some_object", "some_message") end function init(self) -- Wait 2s then call send_first() timer.delay(2, false, send_first) end local function send_second() msg.post("another_object", "another_message") end function on_message(self, message_id, message, sender) if message_id == hash("response") then -- Wait 5s then call send_second() timer.delay(5, false, send_second) end end ``` This is cleaner and easier to follow. We get rid of internal state variables that are often hard to follow through the logic---and which might lead to subtle bugs. We also dispose of the `update()` function completely. That relieves the engine from calling our script 60 times a second, even if it's just idling. ## Preprocessing It is possible to use a Lua preprocessor and special markup to conditionally include code based on the build variant. Example: ```lua -- Use one of the following keywords: RELEASE, DEBUG or HEADLESS --#IF DEBUG local lives_num = 999 --#ELSE local lives_num = 3 --#ENDIF ``` The preprocessor is available as a build extension. Learn more about how to install and use it on the [extension page on GitHub](https://github.com/defold/extension-lua-preprocessor). ## Editor support The Defold editor supports Lua script editing with syntax coloring and auto-completion. To fill out Defold function names, press *Ctrl+Space* to bring up a list of the functions matching what you are typing. # Properties {#manuals:properties} Defold exposes properties for game objects, components and GUI nodes that can be read, set and animated. The following types of properties exist: * System defined game object transforms (position, rotation and scale) and component specific properties (for example a sprite's pixel size or a collision object's mass) * User defined script component properties defined in Lua scripts (see [Script properties documentation](#manuals:script-properties) for details) * GUI node properties * Shader constants defined in shaders and material files (see [Material documentation](#manuals:material) for details) Numeric properties display a drag handle when you hover over their input field. You can increase/decrease their value, by dragging the handle right/left or up/down respectively. Depending on where a property is found, you access it via a generic function, or a property-specific function. Many of the properties can be automatically animated. Animating properties through the built-in system is highly recommended over manipulating the properties yourself (inside an `update()` function), both for performance reasons as well as convenience. Composite properties of type `vector3`, `vector4` or `quaternion` also expose their sub-components (`x`, `y`, `z` and `w`). You can address the components individually by suffixing the name with a dot (`.`) and the name of the component. For example, to set the x-component of a game object's position: ```lua -- Set the x position of "game_object" to 10. go.set("game_object", "position.x", 10) ``` The functions `go.get()`, `go.set()` and `go.animate()` take a reference as their first parameter and a property identifier as their second. The reference identifies the game object or component and can be a string, a hash or a URL. URLs are explained in detail in the [addressing manual](#manuals:addressing). The property identifier is a string or hash that names the property: ```lua -- Set the x-scale of the sprite component local url = msg.url("#sprite") local prop = hash("scale.x") go.set(url, prop, 2.0) ``` For GUI nodes, the node identifier is provided as the first parameter to the property specific function: ```lua -- Get the color of the button local node = gui.get_node("button") local color = gui.get_color(node) ``` ## Game object and component properties All game objects, and some component types have properties that can be read and manipulated in runtime. Read these values with [`go.get()`](https://defold.com/ref/go#go.get) and write them with [`go.set()`](https://defold.com/ref/go#go.set). Depending on the property value type, you can animate the values with [`go.animate()`](https://defold.com/ref/go#go.animate). A small set of the properties are read only. `get` : Can be read with [`go.get()`](https://defold.com/ref/go#go.get). `get+set` : Can be read with [`go.get()`](https://defold.com/ref/go#go.get) and written with [`go.set()`](https://defold.com/ref/go#go.set). Numerical values can be animated with [`go.animate()`](https://defold.com/ref/go#go.animate). *GAME OBJECT PROPERTIES* | property | description | type | | | ---------- | -------------------------------------- | --------------- | ---------------- | | *position* | The local position of the game object. | `vector3` | `get+set` | | *rotation* | Local rotation of game object, expressed as a quaternion. | `quaternion` | `get+set` | | *euler* | Local rotation of game object, Euler angles. | `vector3` | `get+set` | | *scale* | Local non uniform scale of the game object, expressed as a vector where each component contains a multiplier along each axis. To double the size in x and y, provide vmath.vector3(2.0, 2.0, 0) | `vector3` | `get+set` | | *scale.xy* | Local non uniform scale of the game object, expressed as a vector where each component contains a multiplier along X and Y axis.| `vector3` | `get+set` | Specific functions for working with the game object transform also exist; they are `go.get_position()`, `go.set_position()`, `go.get_rotation()`, `go.set_rotation()`, `go.get_scale()`, `go.set_scale()` and `go.set_scale_xy()`. *SPRITE COMPONENT PROPERTIES* | property | description | type | | | ---------- | -------------------------------------- | --------------- | ---------------- | | *size* | The non scaled size of the sprite---its size as taken from the source atlas. | `vector3` | `get` | | *image* | The texture path hash of the sprite. | `hash` | `get`| | *scale* | Non uniform scale of the sprite . | `vector3` | `get+set`| | *scale.xy* | Non uniform scale of the sprite along X and Y axis. | `vector3` | `get+set`| | *material* | The material used by the sprite. | `hash` | `get+set`| | *cursor* | Position (between 0--1) of playback cursor. | `number` | `get+set`| | *playback_rate* | The framerate of the flipbook animation. | `number` | `get+set`| *COLLISION OBJECT COMPONENT PROPERTIES* | property | description | type | | | ---------- | -------------------------------------- | --------------- | ---------------- | | *mass* | The mass of the collision object. | `number` | `get` | | *linear_velocity* | The current linear velocity of the collision object. | `vector3` | `get` | | *angular_velocity* | The current angular velocity of the collision object. | `vector3` | `get` | | *linear_damping* | Linear damping of the collision object. | `vector3` | `get+set` | | *angular_damping* | Angular damping of the collision object. | `vector3` | `get+set` | *MODEL (3D) COMPONENT PROPERTIES* | property | description | type | | | ---------- | -------------------------------------- | --------------- | ---------------- | | *animation* | The current animation. | `hash` | `get` | | *texture0* | The texture path hash of the model. | `hash` | `get`| | *cursor* | Position (between 0--1) of playback cursor. | `number` | `get+set` | | *playback_rate* | The playback rate of the animation. A multiplier to the animation playback rate. | `number` | `get+set` | | *material* | The material used by the model. | `hash` | `get+set`| *LABEL COMPONENT PROPERTIES* | property | description | type | | | ---------- | -------------------------------------- | --------------- | ---------------- | | *scale* | The scale of the label. | `vector3` | `get+set` | | *scale.xy* | The scale of the label along X and Y axis. | `vector3` | `get+set`| | *color* | The color of the label. | `vector4` | `get+set` | | *outline* | The outline color of the label. | `vector4` | `get+set` | | *shadow* | The shadow color of the label. | `vector4` | `get+set` | | *size* | The size of the label. The size will constrain the text if line break is enabled. | `vector3` | `get+set` | | *material* | The material used by the label. | `hash` | `get+set`| | *font* | The font used by the label. | `hash` | `get+set`| ## GUI node properties GUI nodes also contain properties, but they are read and written through special getter and setter functions. For each property there exists one get- and one set- function. There is also a set of constants defined to use as reference to the properties when animating them. If you need to refer to separate property components you have to use the string name of the property, or a hash of the string name. * `position` (or `gui.PROP_POSITION`) * `rotation` (or `gui.PROP_ROTATION`) * `scale` (or `gui.PROP_SCALE`) * `color` (or `gui.PROP_COLOR`) * `outline` (or `gui.PROP_OUTLINE`) * `shadow` (or `gui.PROP_SHADOW`) * `size` (or `gui.PROP_SIZE`) * `fill_angle` (or `gui.PROP_FILL_ANGLE`) * `inner_radius` (or `gui.PROP_INNER_RADIUS`) * `slice9` (or `gui.PROP_SLICE9`) Note that all color values are encoded in a vector4 where the components correspond to the RGBA values: `x` : The red color component `y` : The green color component `z` : The blue color component `w` : The alpha component *GUI NODE PROPERTIES* | property | description | type | | | ---------- | -------------------------------------- | --------------- | ---------------- | | *color* | The face color of the node. | `vector4` | `gui.get_color()` `gui.set_color()` | | *outline* | The outline color of the node. | `vector4` | `gui.get_outline()` `gui.set_outline()` | | *position* | The position of the node. | `vector3` | `gui.get_position()` `gui.set_position()` | | *rotation* | The rotation of the node expressed as Euler angles--degrees rotated around each axis. | `vector3` | `gui.get_rotation()` `gui.set_rotation()` | | *scale* | The scale of the node expressed as a multiplier along each axis. | `vector3` |`gui.get_scale()` `gui.set_scale()` | | *shadow* | The shadow color of the node. | `vector4` | `gui.get_shadow()` `gui.set_shadow()` | | *size* | The unscaled size of the node. | `vector3` | `gui.get_size()` `gui.set_size()` | | *fill_angle* | The fill angle of a pie node expressed as degrees counter-clockwise. | `number` | `gui.get_fill_angle()` `gui.set_fill_angle()` | | *inner_radius* | The inner radius of a pie node. | `number` | `gui.get_inner_radius()` `gui.set_inner_radius()` | | *slice9* | The edge distances of a slice9 node. | `vector4` | `gui.get_slice9()` `gui.set_slice9()` | # Script properties {#manuals:script-properties} Script properties provide a simple and powerful way of defining and exposing custom properties for a specific game object instance. Script properties can be edited on specific instances directly in the editor and their settings can be used in code to alter the behavior of a game object. There are many cases where script properties are very useful: * When you want to override values for specific instances in the editor, and thereby increase script re-usability. * When you want to spawn a game object with initial values. * When you want to animate the values of a property. * When you want to access state data in one script from another. (Note that if you access properties frequently between objects, it may be better to move the data to a shared storage.) Common use cases are to set the health or speed of a specific enemy AI, the tint color of a pickup object, the atlas of a sprite, or what message a button object should send when pressed---and/or where to send it. ## Defining a script property Script properties are added to a script component by defining them with the `go.property()` special function. The function has to be used at the top level---outside any lifecycle functions like `init()` and `update()`. The default value provided for the property governs the type of the property: `number`, `boolean`, `hash`, `msg.url`, `vmath.vector3`, `vmath.vector4`, `vmath.quaternion` and `resource` (see below). Note that the reversal of the hash value works only in the Debug build to facilitate debugging. In the Release build, the reversed string value does not exist, so using `tostring()` on a `hash` value to extract the string from it is meaningless. ```lua -- can.script -- Define script properties for health and an attack target go.property("health", 100) go.property("target", msg.url()) function init(self) -- store initial position of target. -- self.target is a url referencing another object. self.target_pos = go.get_position(self.target) ... end function on_message(self, message_id, message, sender) if message_id == hash("take_damage") then -- decrease the health property self.health = self.health - message.damage if self.health <= 0 then go.delete() end end end ``` Any script component instance created from this script can then set the property values. Select the script component in the *Outline* view in the editor and the properties appear in the *Properties* view allowing you to edit them: Any property that is overridden with a new instance specific value is marked blue. Click the reset button by the property name to revert the value to the default (as set in the script). Script properties are parsed when building the project. Value expressions are not evaluated. This means that something like `go.property("hp", 3+6)` will not work while `go.property("hp", 9)` will. ## Accessing script properties Any defined script property is available as a stored member in `self`, the script instance reference: ```lua -- my_script.script go.property("my_property", 1) function update(self, dt) -- Read and write the property if self.my_property == 1 then self.my_property = 3 end end ``` User-defined script properties can also be accessed through the get, set and animate functions, the same way as any other property: ```lua -- another.script -- increase "my_property" in "myobject#script" by 1 local val = go.get("myobject#my_script", "my_property") go.set("myobject#my_script", "my_property", val + 1) -- animate "my_property" in "myobject#my_script" go.animate("myobject#my_script", "my_property", go.PLAYBACK_LOOP_PINGPONG, 100, go.EASING_LINEAR, 2.0) ``` ## Factory created objects If you use a factory to create the game object, it is possible to set script properties at creation time: ```lua local props = { health = 50, target = msg.url("player") } local id = factory.create("#can_factory", nil, nil, props) -- Accessing factory-created script properties local url = msg.url(nil, id, "can") local can_health = go.get(url, "health") ``` When spawning a hierarchy of game objects through `collectionfactory.create()` you need to pair object id's with property tables. These are put together in a table and passed to the `create()` function: ```lua local props = {} props[hash("/can1")] = { health = 150 } props[hash("/can2")] = { health = 250, target = msg.url("player") } props[hash("/can3")] = { health = 200 } local ids = collectionfactory.create("#cangang_factory", nil, nil, props) ``` The property values provided via `factory.create()` and `collectionfactory.create()` will override any value set in the prototype file as well as the default values in the script. If several script components attached to a game object define the same property, each component will get initialized with the value provided to `factory.create()` or `collectionfactory.create()`. ## Resource properties Resource properties are defined just like the script properties for the basic data types: ```lua go.property("my_atlas", resource.atlas("/atlas.atlas")) go.property("my_font", resource.font("/font.font")) go.property("my_material", resource.material("/material.material")) go.property("my_texture", resource.texture("/texture.png")) go.property("my_tile_source", resource.tile_source("/tilesource.tilesource")) ``` When a resource property is defined it shows up in the *Properties* view as any other script property, but as a file/resource browser field: You access and use the resource properties using `go.get()` or via the `self` script instance reference and using `go.set()`: ```lua function init(self) go.set("#sprite", "image", self.my_atlas) go.set("#label", "font", self.my_font) go.set("#sprite", "material", self.my_material) go.set("#model", "texture0", self.my_texture) go.set("#tilemap", "tile_source", self.my_tile_source) end ``` # Lua in Defold {#manuals:lua} The Defold engine has the Lua language embedded for scripting. Lua is a lightweight dynamic language that is powerful, fast, and easy to embed. It is widely used as a videogame scripting language. Lua programs are written in a simple procedural syntax. The language is dynamically typed and is run by a bytecode interpreter. It features automatic memory management with incremental garbage collection. This manual will give a quick introduction to the basics of Lua programming in general and what you need to consider when working with Lua in Defold. If you have some experience with Python, Perl, Ruby, Javascript, or a similar dynamic language you will get going pretty quickly. If you are new to programming you might want to start with a Lua book aimed at beginners. There are plenty to choose from. ## Lua versions Defold uses [LuaJIT](https://luajit.org/), a highly optimized version of Lua suitable for use in games and other performance-critical software. It is fully upwards compatible with Lua 5.1 and supports all standard Lua library functions and the full set of Lua/C API functions. LuaJIT also adds several [language extensions](https://luajit.org/extensions.html) and some Lua 5.2 and 5.3 features. We aim to keep Defold the same across all platforms, but we currently have a few minor discrepancies in the Lua language version between platforms: * iOS does not allow JIT compilation. * Nintendo Switch does not allow JIT compilation. * HTML5 uses Lua 5.1.4 instead of LuaJIT. To guarantee that your game works across all supported platforms we strongly recommend that you ONLY use language features from Lua 5.1. ### Standard libraries and extensions Defold includes all of the [Lua 5.1 standard libraries](http://www.lua.org/manual/5.1/manual.html#5) as well as a socket and a bit operation library: - base (`assert()`, `error()`, `print()`, `ipairs()`, `require()` etc) - coroutine - package - string - table - math - io - os - debug - socket (from [LuaSocket](https://github.com/diegonehab/luasocket)) - bitop (from [BitOp](http://bitop.luajit.org/api.html)) All libraries are documented in the [reference API documentation](https://defold.com/ref/go). ## Lua books and resources ### Online resources * [Programming in Lua (first edition)](http://www.lua.org/pil/contents.html) Later editions are available in print. * [Lua 5.1 reference manual](http://www.lua.org/manual/5.1/) * [Learn Lua in 15 Minutes](http://tylerneylon.com/a/learn-lua/) * [Awesome Lua - tutorial section](https://github.com/LewisJEllis/awesome-lua#tutorials) ### Books * [Programming in Lua](https://www.amazon.com/gp/product/8590379868/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i0) - Programming in Lua is the official book about the language, providing a solid base to any programmer who wants to use Lua. Authored by Roberto Ierusalimschy, the chief architect of the language. * [Lua programming gems](https://www.amazon.com/Programming-Gems-Luiz-Henrique-Figueiredo/dp/8590379841) - This collection of articles records some of the existing wisdom and practice on how to program well in Lua. * [Lua 5.1 reference manual](https://www.amazon.com/gp/product/8590379833/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i4) - Also available online (see above) * [Beginning Lua Programming](https://www.amazon.com/Beginning-Lua-Programming-Kurt-Jung/dp/0470069171) ### Videos * [Learn Lua in one video](https://www.youtube.com/watch?v=iMacxZQMPXs) ## Syntax Programs have simple, easy-to-read syntax. Statements are written one on each line and there is no need to mark the end of a statement. You can optionally use semicolons `;` to separate statements. Blocks of code are keyword delimited, ending with the `end` keyword. Comments can be either written in a block or until the end of the line: ```lua --[[ Here is a block of comments that can run over several lines in the source file. --]] a = 10 b = 20 ; c = 30 -- two statements on one line if my_variable == 3 then call_some_function(true) -- Here is a line comment else call_another_function(false) end ``` ## Variables and data types Lua is dynamically typed, meaning variables do not have types, but values do. Unlike in statically typed languages, you can assign any value to any variable as you like. There are eight basic types in Lua: `nil` : This type only has the value `nil`. It usually represents the absence of a useful value, for example, unassigned variables. ```lua print(my_var) -- will print 'nil' since 'my_var' is not yet assigned a value ``` boolean : Has either the value `true` or `false`. Conditions that are `false` or `nil` are made false. Any other value makes it true. ```lua flag = true if flag then print("flag is true") else print("flag is false") end if my_var then print("my_var is not nil nor false!") end if not my_var then print("my_var is either nil or false!") end ``` number : Numbers are internally represented as either 64 bit _integers_ or 64 bit _floating point_ numbers. Lua automatically converts between these representations as needed so you generally don't have to worry about it. ```lua print(10) --> prints '10' print(10.0) --> '10' print(10.000000000001) --> '10.000000000001' a = 5 -- integer b = 7/3 -- float print(a - b) --> '2.6666666666667' ``` string : Strings are immutable sequences of bytes that can contain any 8-bit value, including embedded zeros (`\0`). Lua makes no assumptions about the contents of a string so you can store any data you like in them. String literals are written in single or double quotes. Lua converts between numbers and strings at runtime. Strings can be concatenated with the `..` operator. Strings can contain the following C-style escape sequences: | Sequence | Character | | -------- | --------- | | `\a` | bell | | `\b` | back space | | `\f` | form feed | | `\n` | newline | | `\r` | carriage return | | `\t` | horizontal tab | | `\v` | vertical tab | | `\\` | backslash | | `\"` | double quote | | `\'` | single quote | | `\[` | left square bracket | | `\]` | right square bracket | | `\ddd` | character denoted by its numeric value where `ddd` is a sequence of up to three _decimal_ digits | ```lua my_string = "hello" another_string = 'world' print(my_string .. another_string) --> "helloworld" print("10.2" + 1) --> 11.2 print(my_string + 1) -- error, can't convert "hello" print(my_string .. 1) --> "hello1" print("one\nstring") --> one --> string print("\097bc") --> "abc" multi_line_string = [[ Here is a chunk of text that runs over several lines. This is all put into the string and is sometimes very handy. ]] ``` function : Functions are first-class values in Lua, meaning that you can pass them as parameters to functions and return them as values. Variables assigned to a function contain a reference to the function. You can assign variables to anonymous functions, but Lua provides syntactic sugar (`function name(param1, param2) ... end`) for convenience. ```lua -- Assign 'my_plus' to function my_plus = function(p, q) return p + q end print(my_plus(4, 5)) --> 9 -- Convenient syntax to assign function to variable 'my_mult' function my_mult(p, q) return p * q end print(my_mult(4, 5)) --> 20 -- Takes a function as parameter 'func' function operate(func, p, q) return func(p, q) -- Calls the provided function with parameters 'p' and 'q' end print(operate(my_plus, 4, 5)) --> 9 print(operate(my_mult, 4, 5)) --> 20 -- Create an adder function and return it function create_adder(n) return function(a) return a + n end end adder = create_adder(2) print(adder(3)) --> 5 print(adder(10)) --> 12 ``` table : Tables are the only data-structuring type in Lua. They are associative array _objects_ that are used to represent lists, arrays, sequences, symbol tables, sets, records, graphs, trees, etc. Tables are always anonymous and variables you assign a table to do not contain the table itself, but a reference to it. When initializing a table as a sequence, the first index is `1`, not `0`. ```lua -- Initialize a table as a sequence weekdays = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} print(weekdays[1]) --> "Sunday" print(weekdays[5]) --> "Thursday" -- Initialize a table as a record with sequence values moons = { Earth = { "Moon" }, Uranus = { "Puck", "Miranda", "Ariel", "Umbriel", "Titania", "Oberon" } } print(moons.Uranus[3]) --> "Ariel" -- Build a table from an empty constructor {} a = 1 t = {} t[1] = "first" t[a + 1] = "second" t.x = 1 -- same as t["x"] = 1 -- Iterate over the table key, value pairs for key, value in pairs(t) do print(key, value) end --> 1 first --> 2 second --> x 1 u = t -- u now refers to the same table as t u[1] = "changed" for key, value in pairs(t) do -- still iterating over t! print(key, value) end --> 1 changed --> 2 second --> x 1 ``` userdata : Userdata is provided to allow arbitrary C data to be stored in Lua variables. Defold uses Lua userdata objects to store Hash values (hash), URL objects (url), Math objects (vector3, vector4, matrix4, quaternion), Game objects, GUI nodes (node), Render predicates (predicate), Render targets (render_target) and Render constant buffers (constant_buffer) thread : Threads represent independent threads of execution and are used to implement coroutines. See below for details. ## Operators Arithmetic operators : Mathematic operators `+`, `-`, `*`, `/`, the unary `-` (negation) and exponential `^`. ```lua a = -1 print(a * 2 + 3 / 4^5) --> -1.9970703125 ``` Lua provides automatic conversions between numbers and strings at run time. Any numeric operation applied to a string tries to convert the string to a number: ```lua print("10" + 1) --> 11 ``` Relational/comparison operators : `` (greater than), `=` (greater or equal), `==` (equal), `~=` (not equal). There operators always return `true` or `false`. Values of different types are considered different. If the types are the same, they are compared according to their value. Lua compares tables, userdata, and functions by reference. Two such values are considered equal only if they refer to the same object. ```lua a = 5 b = 6 if a <= b then print("a is less than or equal to b") end print("A" < "a") --> true print("aa" < "ab") --> true print(10 == "10") --> false print(tostring(10) == "10") --> true ``` Logical operators : `and`, `or`, and `not`. `and` returns its first argument if it is `false`, otherwise it returns its second argument. `or` returns its first argument if it is not `false`, otherwise it returns its second argument. ```lua print(true or false) --> true print(true and false) --> false print(not false) --> true if a == 5 and b == 6 then print("a is 5 and b is 6") end ``` Concatenation : Strings can be concatenated with the `..` operator. Numbers are converted to strings when concatenated. ```lua print("donkey" .. "kong") --> "donkeykong" print(1 .. 2) --> "12" ``` Length : The unary length operator `#`. The length of a string is its number of bytes. The length of a table is its sequence length, the number of indices that are numbered from `1` and upwards where the value is not `nil`. Note: If the sequence has `nil` value "holes" in it, the length can be any index preceding a `nil` value. ```lua s = "donkey" print(#s) --> 6 t = { "a", "b", "c", "d" } print(#t) --> 4 u = { a = 1, b = 2, c = 3 } print(#u) --> 0 v = { "a", "b", nil } print(#v) --> 2 ``` ## Flow control Lua provides the usual set of flow control constructs. if---then---else : Test a condition, execute the `then` part if the condition is true, otherwise execute the (optional) `else` part. Instead of nesting `if` statements you can use `elseif`. This replaces a switch-statement that Lua does not have. ```lua a = 5 b = 4 if a < b then print("a is smaller than b") end if a == '1' then print("a is 1") elseif a == '2' then print("a is 2") elseif a == '3' then print("a is 3") else print("I have no idea what a is...") end ``` while : Test a condition and execute the block as long as it's true. ```lua weekdays = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} -- Print each weekday i = 1 while weekdays[i] do print(weekdays[i]) i = i + 1 end ``` repeat---until : Repeats the block until a condition is true. The condition is tested after the body so it will execute at least once. ```lua weekdays = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} -- Print each weekday i = 0 repeat i = i + 1 print(weekdays[i]) until weekdays[i] == "Saturday" ``` for : Lua has two types of `for` loop: numeric and generic. The numeric `for` takes 2 or 3 numeric values whereas the generic `for` iterates over all values returned by an _iterator_ function. ```lua -- Print the numbers 1 to 10 for i = 1, 10 do print(i) end -- Print the numbers 1 to 10 and increment with 2 each time for i = 1, 10, 2 do print(i) end -- Print the numbers 10 to 1 for i=10, 1, -1 do print(i) end t = { "a", "b", "c", "d" } -- Iterate over the sequence and print the values for i, v in ipairs(t) do print(v) end ``` break and return : Use the `break` statement to break out of an inner block of a `for`, `while` or `repeat` loop. Use `return` to return a value from a function or to finish the execution of a function and return to the caller. `break` or `return` can appear only as the last statement of a block. ```lua a = 1 while true do a = a + 1 if a >= 100 then break end end function my_add(a, b) return a + b end print(my_add(10, 12)) --> 22 ``` ## Locals, globals and lexical scoping All variables that you declare are by default global, meaning that they are available through all parts of the Lua runtime context. You can explicitly declare variables `local`, meaning that the variable will only exist within the current scope. Each Lua source file defines a separate scope. Local declarations on the topmost level in a file mean the variable is local to the Lua script file. Each function creates another nested scope and each control structure block creates additional scopes. You can explicitly create a scope with the `do` and `end` keywords. Lua is lexically scoped, meaning that a scope has full access to _local_ variables from the enclosing scope. Note that the local variables must be declared before their use. ```lua function my_func(a, b) -- 'a' and 'b' are local to this function and available through its scope do local x = 1 end print(x) --> nil. 'x' is not available outside the do-end scope print(foo) --> nil. 'foo' is declared after 'my_func' print(foo_global) --> "value 2" end local foo = "value 1" foo_global = "value 2" print(foo) --> "value 1". 'foo' is available in the topmost scope after declaration. ``` Note that if you declare functions `local` in a script file (which is generally a good idea) you need to watch out how you order the code. You can use forward declarations if you have functions that mutually call each other. ```lua local func2 -- Forward declare 'func2' local function func1(a) print("func1") func2(a) end function func2(a) -- or func2 = function(a) print("func2") if a < 10 then func1(a + 1) end end function init(self) func1(1) end ``` If you write a function enclosed in another function, it too has full access to local variables from the enclosing function. This is a very powerful construct. ```lua function create_counter(x) -- 'x' is a local variable in 'create_counter' return function() x = x + 1 return x end end count1 = create_counter(10) count2 = create_counter(20) print(count1()) --> 11 print(count2()) --> 21 print(count1()) --> 12 ``` ## Variable shadowing Local variables declared in a block will shadow variables from a surrounding block with the same name. ```lua my_global = "global" print(my_global) -->"global" local v = "local" print(v) --> "local" local function test(v) print(v) end function init(self) v = "apple" print(v) --> "apple" test("banana") --> "banana" end ``` ## Coroutines Functions execute from beginning to end and there is no way to stop them midway through. Coroutines allow you to do that, which can be very convenient in some cases. Suppose we want to create a very specific frame-by-frame animation where we move a game object from y position `0` to some very specific y positions from frame 1 to frame 5. We could solve that with a counter in the `update()` function (see below) and a list of the positions. However, with a coroutine, we get a very clean implementation that is easy to extend and work with. All state is contained within the coroutine itself. When a coroutine yields it returns control back to the caller but remembers its execution point so it can continue from there later on. ```lua -- This is our coroutine local function sequence(self) coroutine.yield(120) coroutine.yield(320) coroutine.yield(510) coroutine.yield(240) return 440 -- return the final value end function init(self) self.co = coroutine.create(sequence) -- Create the coroutine. 'self.co' is a thread object go.set_position(vmath.vector3(100, 0, 0)) -- Set initial position end function update(self, dt) local status, y_pos = coroutine.resume(self.co, self) -- Continue execution of coroutine. if status then -- If the coroutine is still not terminated/dead, use its yielded return value as a new position go.set_position(vmath.vector3(100, y_pos, 0)) end end ``` ## Lua contexts in Defold All variables that you declare are by default global, meaning that they are available through all parts of the Lua runtime context. Defold has a setting *shared_state* setting in *game.project* that controls this context. If the option is set, all scripts, GUI scripts, and the render script are evaluated in the same Lua context and global variables are visible everywhere. If the option is not set, the engine executes scripts, GUI scripts, and the render script in separate contexts. Defold allows you to use the same script file in several separate game object components. Any locally declared variables are shared between components that run the same script file. ```lua -- 'my_global_value' will be available from all scripts, gui_scripts, render script and modules (Lua files) my_global_value = "global scope" -- this value will be shared through all component instances that use this particular script file local script_value = "script scope" function init(self, dt) -- This value will be available on this script component instance self.foo = "self scope" -- this value will be available inside init() and after it's declaration local local_foo = "local scope" print(local_foo) end function update(self, dt) print(self.foo) print(my_global_value) print(script_value) print(local_foo) -- will print nil, since local_foo is only visible in init() end ``` ## Performance considerations In a high-performance game that is intended to run at a smooth 60 FPS small performance mistakes can have a large impact on the experience. There are some simple general things to consider and some things that might not seem problematic. Beginning with the simple things. It is generally a good idea to write straightforward code that does not contain unnecessary loops. Sometimes you do need to iterate over lists of things, but be careful if the list of things is sufficiently large. This example runs in slightly over 1 millisecond on a pretty decent laptop, which can make all the difference if each frame is only 16 milliseconds long (at 60 FPS) and with the engine, render script, physics simulation, and so forth eating up a chunk of that. ```lua local t = socket.gettime() local table = {} for i=1,2000 do table[i] = vmath.vector3(i, i, i) end print((socket.gettime() - t) * 1000) -- DEBUG:SCRIPT: 0.40388 ``` Use the value returned from `socket.gettime()` (seconds since system epoch) to benchmark suspect code. ## Memory and garbage collection Lua's garbage collection runs automatically in the background by default and reclaims memory that the Lua runtime has allocated. Collecting lots of garbage can be a time-consuming task so it is good to keep down the number of objects that need to be garbage collected: * Local variables are in themselves free and will not generate garbage. (i.e. `local v = 42`) * Each _new unique_ string creates a new object. Writing `local s = "some_string"` will create a new object and assign `s` to it. The local `s` itself will not generate garbage, but the string object will. Using the same string multiple times adds no additional memory cost. * Each time a table constructor is executed (`{ ... }`) a new table is created. * Executing a _function statement_ creates a closure object. (i.e. executing the statement `function () ... end`, not calling a defined function) * Vararg functions (`function(v, ...) end`) create a table for the ellipsis each time the function is _called_ (in Lua before version 5.2, or if not using LuaJIT). * `dofile()` and `dostring()` * Userdata objects There are many cases where you can avoid creating new objects and instead reuse the ones you already have. For example. The following is common at the end of each `update()`: ```lua -- Reset velocity self.velocity = vmath.vector3() ``` It's easy to forget that each call to `vmath.vector3()` creates a new object. Let's find out how much memory one `vector3` uses: ```lua print(collectgarbage("count") * 1024) -- 88634 local v = vmath.vector3() print(collectgarbage("count") * 1024) -- 88704. 70 bytes in total has been allocated ``` 70 bytes has been added between the calls to `collectgarbage()`, but this includes allocations for more than the `vector3` object. Each printing of the result from `collectgarbage()` builds a string which in itself adds 22 bytes of garbage: ```lua print(collectgarbage("count") * 1024) -- 88611 print(collectgarbage("count") * 1024) -- 88633. 22 bytes allocated ``` So a `vector3` weighs in at 70-22=48 bytes. That is not much, but if you create _one_ each frame in a 60 FPS game it's suddenly 2.8 kB of garbage per second. With 360 script components that each create one `vector3` every frame we're looking at 1 MB of garbage generated per second. The numbers can add up very quickly. When the Lua runtime collects garbage it may eat up many precious milliseconds---especially on mobile platforms. One way to avoid allocations is to create a `vector3` and then keep working with the same object. For instance, to reset a `vector3` we can use the following construct: ```lua -- Instead of doing self.velocity = vmath.vector3() which creates a new object -- we zero an existing velocity vector object's components self.velocity.x = 0 self.velocity.y = 0 self.velocity.z = 0 ``` The default garbage-collecting scheme may not be optimal for some time-critical applications. If you see a stutter in your game or app, you might want to tune how Lua collects garbage through the [`collectgarbage()`](https://defold.com/ref/base/#collectgarbage) Lua function. You can, for instance, run the collector for a short time every frame with a low `step` value. To get an idea how much memory your game or app is eating, you can print the current amount of garbage bytes with: ```lua print(collectgarbage("count") * 1024) ``` ## Best practices A common implementation design consideration is how to structure code for shared behaviors. Several approaches are possible. Behaviors in a module : Encapsulating a behavior in a module allows you to easily share code between different game objects’ script components (and GUI scripts). When writing module functions it is generally best to write strictly functional code. There are cases where stored state or side effects are a necessity (or lead to cleaner design). If you have to store the internal state in the module, be aware that components share Lua contexts. See the [Modules documentation](#manuals:modules) for details. Also, even if it is possible to have module code directly modify the internals of a game object (by passing `self` to a module function) we strongly discourage you from doing so since you will create very tight coupling. A helper game object with encapsulated behavior : Just like you can contain script code in a Lua module, you can contain it in a game object with a script component. The difference is that if you contain it in a game object you can communicate with it strictly through message passing. Grouping game object with helper behavior object inside a collection : In this design, you can create a behavior game object that automatically acts upon another target game object, either by a predefined name (the user has to rename the target game object to match) or through a `go.property()` URL that points to the target game object. The benefit of this setup is that you can drop a behavior game object into a collection containing the target object. Zero additional code is needed. In situations where you need to manage large quantities of game objects, this design is not preferable since the behavior object is duplicated for each instance and each object will cost memory. # Application Security {#manuals:application-security} Application security is a broad topic which covers everything from secure development practices to securing your game content after it has been released. This manual will cover a number of areas and put them in the context of application security when using the Defold engine, tools and services: * Intellectual property protection * Anti-cheat solutions * Secure network communication * Use of third-party software * Use of cloud build servers * Downloadable content ## Securing your intellectual property from theft A concern most developers have is how to protect their creations from theft. Copyright, patents and trademarks can from a legal standpoint be used to protect the different aspects of the intellectual property of video games. Copyright gives its owner the exclusive right to distribute the creative work, Patents protects any inventions and Trademarks protects names, symbols and logos. It may also be desirable to take technical precautions to protect the creative work of a game. It is however important to keep in mind that once the game is in the hands of the player it is possible to find ways to extract the assets. This can be achieved by reverse engineering the game application and files, but also by using tools to extract texture and models as they are sent to the GPU or when other assets are loaded into memory. For this reason it is our general stance that if users are determined to extract the assets of a game, they will be able to do so. Developers can add their own protection to make it harder, __but not impossible__, to extract the assets. This typically includes various means of encryption and obfuscation to protect and hide game assets. ### Source code obfuscation Applying source code obfuscation is an automated process where the source code is deliberately made difficult for humans to understand, without impacting the program’s output. The purpose is usually to protect against theft, but also to make cheating harder. It is possible to apply source code obfuscation in Defold either as a prebuild step or as an integrated part of the Defold build process. With prebuild obfuscation the source code is obfuscated using an obfuscation tool before the Defold build process is started. Build-time obfuscation on the other hand is integrated into the build process using a Lua builder plugin. A Lua builder plugin takes the raw source code as input and returns an obfuscated version of the source code as output. One example of build-time obfuscation is shown in the [Prometheus extension](https://github.com/defold/extension-prometheus), based on the Prometheus Lua obfuscator available on GitHub. Below you will find an example of using Prometheus to aggressively obfuscate a snippet of code (note that this kind of heavy obfuscation will have an impact on the runtime performance of the Lua code): Example: ``` function init(self) print("hello") test.greet("Bob") end ``` Obfuscated output: ``` local v={"+qdW","ZK0tEKf=";"XP/IX3+="}for o,J in ipairs({% raw %}{{1;3};{1,1},{2,3}}{% endraw %})do while J[1]=J or x(X,S+1,S+1)~="="then L(H,W(h((k%65536)/256)))end break end S=S+1 end d[v]=w(H)end end end local function o(o)test[J(-45815)](o)end function init(v)print(J(-45813))o(J(-45814))end ``` ### Resource encryption During the Defold build process the game resources are processed and transformed into formats suitable for runtime consumption by the Defold engine. Textures are compiled into the Basis Universal format, the collections, game objects and components are converted from human readable text representation to binary counterparts and the Lua source code is processed and compiled into bytecode. Other assets such as sound files are used as-is. When this process is completed the assets are added to the game archive, one by one. The game archive is a large binary file and the location of each resource within the archive is stored in an archive index file. The format is documented [here](https://github.com/defold/defold/blob/dev/engine/docs/ARCHIVE_FORMAT.md). Before Lua source files are added to the archive they are also optionally encrypted. The default encryption provided in Defold is a simple block cipher used to prevent strings in the code from being immediately visible if the game archive is inspected using a binary file viewer tool. It should not be considered cryptographically secure since the Defold source code is available on GitHub with the cipher key visible in the source code. It is possible to add custom encryption to Lua source files by implementing a Resource encryption plugin. A Resource encryption plugin consists of a build-time part to encrypt resources as part of the build process and a runtime part to decrypt resources when they are read from the game archive. A basic Resource Encryption plugin which can be used as the starting point for your own encryption is [available on GitHub](https://github.com/defold/extension-resource-encryption). ### Encoding project configuration values The *game.project* file will be included as-is in your application bundle. Sometimes you may wish to store public API access keys or similar values, that are of a sensitive, but perhaps not private nature. To harden security for such values they can be included into the application binary, instead of stored in *game.project*, and still be accessible to Defold API functions such as `sys.get_config_string()` and similar functions. You can do so by adding a native extension in your *game.project* and using the `DM_DECLARE_CONFIGFILE_EXTENSION` macro to provide your own overrides for getting config values using the Defold API functions. An example project that can be used as a starting point is [available on GitHub](https://github.com/defold/example-configfile-extension/tree/master). ## Securing your game against cheaters Cheating in video games has existed for as long as the games industry itself. Cheat codes used to be shared in popular video games magazines and special cheat cartridges were sold for the early home computers. As the industry and the games have evolved so have the cheaters and their methods. Some of the most popular cheating mechanism for games are: * Repackaging of game content to inject custom logic * Speed hacks to make a game run faster or slower than normal * Automation and visual analysis for auto aiming and bots * Code and memory injection to modify scores, lives, ammo etc Protecting against cheaters is hard, bordering on impossible. Even cloud gaming, where games are run on remote servers and streamed directly to a user's device are not fully exempt from cheaters. Defold does not provide any anti-cheat solutions in the engine or tools and instead defer any such work to one of the many companies specialize in providing anti-cheat solutions for games. ## Securing your network communication Defold socket and HTTP communication support secure socket connections. It is recommended to use secure connections for any server communication to authenticate the server and to protect the privacy and integrity of any exchanged data while in transit from client to server and vice versa. Defold uses the popular and widely adopted open source [Mbed TLS](https://github.com/Mbed-TLS/mbedtls) implementation of the TLS and SSL protocols. Mbed TLS is developed by ARM and their technology partners. ### SSL certificate validation To prevent man in the middle attacks on your network communication it is possible to validate the certificate chain during the SSL handshake when negotiating a connection with a server. This can be done by providing a list of public keys to the network client in Defold. For more information on securing your network communication please read the section about SSL verification in the [network manual](#manuals:networking). ## Securing your use of third-party software While it is not necessary to use any third-party libraries or native extensions to create a game it has become a very common practice among developers to use assets from the official [Asset Portal](https://defold.com/assets/) to speed up development. The Asset Portal contains a large selection of assets, ranging from integrations with third-party SDKs, to screen managers, UI libraries, cameras and much more. None of the assets in the Asset Portal have been reviewed by the Defold Foundation and we do not take responsibility for any damage to your computer system or other device or loss of data that results from use of any asset obtained through the Asset Portal. You can read the fine print in our [Terms and Conditions](https://defold.com/terms-and-conditions/#3-no-warranties). We recommend that you review any asset before use, and once you have deemed that it is suitable for use in your project you create a fork or copy of the asset to ensure that it doesn’t change without you noticing it. ## Securing your use of cloud build servers The Defold cloud build servers (aka extender servers) were created to help developers add new functionality to the Defold engine without requiring a rebuild of the engine itself. When a Defold project containing native code is built for the first time the native code and any associated resources are sent to the cloud build servers where a custom version of the Defold engine is created and sent back to the developer. The same process is applied when a project is built using a custom application manifest to remove unused components from the engine. The cloud build servers are hosted with AWS and created according to security best practices. The Defold Foundation does however not guarantee that the cloud build servers will meet your requirements, be free from defects, virus free, secure or error free, or that your use of the servers will be uninterrupted or secure. You can read the fine print in our [Terms and Conditions](https://defold.com/terms-and-conditions/#3-no-warranties). If the security and availability of the builds servers are of concern to you we recommend that you set up your own private build servers. Instructions on how to set up your own server can be found in the [main readme file](https://github.com/defold/extender) of the extender repository on GitHub. ## Securing your downloadable content The Defold Live Update system allows developers to exclude content from the main game bundle for download and use at a later time. A typical use case is to download additional levels, maps or worlds as the player progresses through the game. When excluded content is downloaded and prepared for use in a game, the content will be cryptographically verified by the engine before use to ensure that it has not been tampered with. The verification consists of a number of checks: * Is the binary format correct? * Is the downloaded content supported by the currently running engine version? * Is the downloaded content signed with the correct public-private key pair? * Is the downloaded content complete and not missing any files? You can read more about this process in the [Live Update manual](#manuals:live-update). # Lua modules {#manuals: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. 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. ## Requiring Lua 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 `New... ▸ Lua Module`. Give the file a unique name and press `Ok`: Suppose the following code is added to the file "`main/anim.lua`": ```lua 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 ``` Then it's possible for any script to require this file and use the function: ```lua require "main.anim" function update(self, dt) -- update position, set direction etc ... -- set animation local anim = direction_animation(self.dir, "player") if anim ~= self.current_anim then sprite.play_flipbook("#sprite", anim) self.current_anim = anim end end ``` 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. 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. 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 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 local M = {} -- private local message = "Hello world!" function M.hello() print(message) end return M ``` The module can then be used. Again, it is preferred to assign it to a local variable: ```lua local m = require "mymodule" m.hello() --> "Hello world!" ``` ## Hot reloading modules Consider a simple module: ```lua -- module.lua local M = {} -- creates a new table in the local scope M.value = 4711 return M ``` And a user of the module: ```lua local m = require "module" print(m.value) --> "4711" (even if "module.lua" is changed and hot reloaded) ``` If you hot reload the module file the code is run again, but nothing happens with `m.value`. Why is that? 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. Secondly, Lua caches required files. The first time a file is required, it is put in the table [`package.loaded`](https://defold.com/ref/package/#package.loaded) so it can be read faster on subsequent 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`. 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. 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 --- module.lua -- Replace with local M = {} when done uniquevariable12345 = uniquevariable12345 or {} local M = uniquevariable12345 M.value = 4711 return M ``` ## Modules and state Stateful modules keep an internal state that is shared between all users of the module and can be compared to singletons: ```lua local M = {} -- all users of the module will share this table local state = {} function M.do_something(foobar) table.insert(state, foobar) 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. 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()) ``` # Working with files {#manuals:file-access} There are many different ways to create and/or access files. The file paths and the ways your access these files varies depending on the type of file and the location of the file. ## Functions for file and folder access Defold provides several different functions to work with files: * You can use the standard [`io.*` functions](https://defold.com/ref/stable/io/) to read and write files. These functions give you very fine-grained control over the entire I/O process. ```lua -- open myfile.txt for writing in binary mode -- returns nil plus error message on failure local f, err = io.open("path/to/myfile.txt", "wb") if not f then print("Something went wrong while opening the file", err) return end -- write to the file, flush it to disk and then close the file f:write("Foobar") f:flush() f:close() -- open myfile.txt for reading in binary mode -- returns nil plus error message on failure local f, err = io.open("path/to/myfile.txt", "rb") if not f then print("Something went wrong while opening the file", err) return end -- read the entire file as a string -- returns nil on failure local s = f:read("*a") if not s then print("Error while reading file") return end print(s) -- Foobar ``` * You can use [`os.rename()`](https://defold.com/ref/stable/os/#os.rename:oldname-newname) and [`os.remove()`](https://defold.com/ref/stable/os/#os.remove:filename) to rename and remove files. * You can use [`sys.save()`](https://defold.com/ref/stable/sys/#sys.save:filename-table) and [`sys.load()`](https://defold.com/ref/stable/sys/#sys.load:filename) to read and write Lua tables. Additional [`sys.*`](https://defold.com/ref/stable/sys/) functions exist to help with platform independent file path resolution. ```lua -- get a platform independent path to the file "highscore" for application "mygame" local path = sys.get_save_file("mygame", "highscore") -- save a Lua table with some data local ok = sys.save(path, { highscore = 100 }) if not ok then print("Failed to save", path) return end -- load the data local data = sys.load(path) print(data.highscore) -- 100 ``` ## File and folder locations File and folder locations can be divided into three categories: * Application specific files created by your application * Files and folders bundled with your application * System specific files accessed by your application ### How to save and load application specific files When saving and loading application specific files such as high scores, user settings and game state it is recommended to do so in a location provided by the operating system and intended specifically for this purpose. You can use [`sys.get_save_file()`](https://defold.com/ref/stable/sys/#sys.get_save_file:application_id-file_name) to get the OS specific absolute path to a file. Once you have the absolute path you can use the `sys.*`, `io.*` and `os.*` functions (see above). [Check the example showing how to use `sys.save()` and `sys.load()`](https://defold.com/examples/file/sys_save_load/). ### How to access files bundled with the application You can include files with your application using bundle resources and custom resources. #### Custom Resources Custom resources are bundled in the main game archive using the [*Custom Resources* field](#manuals:project-settings) in *game.project*. The *Custom Resources* field should contain a comma separated list of resources that will be included in the main game archive. If directories are specified, all files and directories in that directory are recursively included. You can read the files using [`sys.load_resource()`](https://defold.com/ref/sys/#sys.load_resource). ```lua -- Load level data into a string local data, error = sys.load_resource("/assets/level_data.json") -- Decode json string to a Lua table if data then local data_table = json.decode(data) pprint(data_table) else print(error) end ``` #### Bundle Resources Bundle resources are additional files and folders located as a part of your application bundle using the [*Bundle Resources* field](#manuals:project-settings) in *game.project*. The *Bundle Resources* field should contain a comma separated list of directories containing resource files and folders that should be copied as-is into the resulting package when bundling. The directories must be specified with an absolute path from the project root, for example `/res`. The resource directory must contain subfolders named by `platform`, or `architecture-platform`. Supported platforms are `ios`, `android`, `osx`, `win32`, `linux`, `web`, `switch` A subfolder named `common` is also allowed, containing resource files common for all platforms. Example: ``` res ├── win32 │ └── mywin32file.txt ├── common │ └── mycommonfile.txt └── android ├── myandroidfile.txt └── res └── xml └── filepaths.xml ``` You can use [`sys.get_application_path()`](https://defold.com/ref/stable/sys/#sys.get_application_path:) to get the path to where the application is stored. Use this application base path to create the final absolute path to the files you need access to. Once you have the absolute path of these files you can use the `io.*` and `os.*` functions to access the files. ```lua local path = sys.get_application_path() local f = io.open(path .. "/mycommonfile.txt", "rb") local txt, err = f:read("*a") if not txt then print(err) return end print(txt) ``` For security reasons browsers (and by extension any JavaScript running in a browser) is prevented from accessing system files. File operations in HTML5 builds in Defold still work, but only on a "virtual file system" using the IndexedDB API in the browser. What this means is that there is no way to access bundle resources using `io.*` or `os.*` functions. You can however access bundle resources using `http.request()`. #### Custom and Bundle resources - comparison | Characteristic | Custom Resources | Bundle Resources | |-----------------------------|-------------------------------------------|------------------------------------------------| | Loading speed | Faster - files loaded from binary archive | Slower - files loaded from filesystem | | Load partial files | No - only entire files | Yes - read arbitrary bytes from file | | Modify files after bundling | No - files stored inside a binary archive | Yes - files stored on the local file system | | HTML5 support | Yes | Yes - but access through http and not file I/O | ### System file access Access to system files may be restricted by the operating system for security reasons. You can use the [`extension-directories`](https://defold.com/assets/extensiondirectories/) native extension to get the absolute path to some common system directories (ie documents, resource, temp). Once you have the absolute path of these files you can use the `io.*` and `os.*` functions to access the files (see above). For security reasons browsers (and by extension any JavaScript running in a browser) is prevented from accessing system files. File operations in HTML5 builds in Defold still work, but only on a "virtual file system" using the IndexedDB API in the browser. What this means is that there is no way to access system files in HTML5 builds. ## Extensions The [Asset Portal](https://defold.com/assets/) contains several assets to simplify file and folder access. Some examples: * [Lua File System (LFS)](https://defold.com/assets/luafilesystemlfs/) - Functions to work with directories, file permissions etc * [DefSave](https://defold.com/assets/defsave/) - A module to help you save / load config and player data between session. # Networking {#manuals:networking} It is not uncommon for games to have some kind of connection to a backend service, perhaps to post scores, handle match making or store saved games in the cloud. Many games also have peer to peer connections where game clients communicate directly with each other, without involvement of a central server. Network connections and the exchange of data can be made using several different protocols and standards. Learn more about the different ways to use network connections in Defold: * [HTTP Requests](#manuals:http-requests) * [Socket connections](#manuals:socket-connections) * [WebSocket connections](#manuals:websocket-connections) * [Online services](#manuals:online-services) ## Technical details ### IPv4 and IPv6 Defold supports IPv4 and IPv6 connections for sockets and HTTP requests. ### Secure connections Defold supports secure SSL connections for sockets and HTTP requests. Defold can optionally also verify the SSL certificate of any secure connection. SSL verification will be enabled when a PEM file containing public CA-root certificate keys or a self-signed certificate public key is provided in the [SSL Certificates setting](#manuals:project-settings)) field of the Network section in *game.project*. A list of CA-root certificates is included in `builtins/ca-certificates`, but it is recommended to create a new PEM file and copy-paste the needed CA-root certificates depending on the server(s) the game connects to. ## HTTP requests {#manuals:http-requests} Defold can make normal HTTP requests using the `http.request()` function. ### HTTP GET This is the most basic request to get some data from the server. Example: ```lua local function handle_response(self, id, response) print(response.status, response.response) end http.request("https://www.defold.com", "GET", handle_response) ``` This will make an HTTP GET request to https://www.defold.com. The function is asynchronous and will not block while making the request. Once the request has been made and a server has sent a response it will invoke/call the provided callback function. The callback function will receive the full server response, including status code and response headers. See below for additional information about how to work with the response table. HTTP requests are automatically cached in the client to improve network performance. The cached files are stored in an OS specific application support path in a folder named `defold/http-cache`. You usually don't have to care about the HTTP cache but if you need to clear the cache during development you can manually delete the folder containing the cached files. On macOS this folder is located in `%HOME%/Library/Application Support/Defold/http-cache/` and on Windows in `%APP_DATA%/defold/http-cache`. ### HTTP POST When sending data, like a score or some authentication data, to a server it is typically done using a POST requests: ```lua local function handle_response(self, id, response) print(response.status, response.response) end local body = "12345" http.request("https://www.myserver.com/score", "POST", handle_response, nil, body) ``` ### Other HTTP methods Defold HTTP requests also support the HEAD, DELETE and PUT methods. The CONNECT method is also supported (see section about proxy connections below). ### How to work with the HTTP response The `response` table returned in the callback contains all of the information necessary to implement granular response handling. Two of the key fields are `status` and `response`: ```lua local function handle_response(self, id, response) -- check the response status code. Common response codes: -- 200 OK - the request completed successfully -- 301 Moved permanently - the requested data has moved, see redirect header -- 307 Temporary redirect - same as above -- 208 Permanent redirect - same as above -- 400 Bad Request - the request was malformed -- 401 Unauthorized - the client must authenticate itself -- 404 Not Found - the server cannot find the information -- https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status if response.status == 200 then -- the response data -- this can be anything from plain text, json encoded data or binary data print(response.response) json.decode(response.response) sys.save(..., response.response) end end ``` When the response contains a large blob of binary data such as an image or a music track it might make sense to write the data to a file instead of loading it into memory: ```lua -- in this example we download myimage.png and write it directly to a file on disk local options = { path = sys.get_save_file("mygame", "myimage.png") } local function handle_response(self, id, response) if response.status == 200 then print("File was successfully written to:", response.path) print("File size:", response.document_size) print("File path:", response.path) else print("File was not written to disk:", response.error) end end http.request("https://www.foobar.com/myimage.png", "GET", handle_response) ``` Another use-case for loading large amounts of data over the network is sound streaming, when "chunks" of sound data are loaded from a URL and fed into a sound resource. A complete example can be found in the [Sound Streaming manual](/sound-streaming#sound-streaming). ### Request headers It is possible to set additional headers when sending a request. This can for instance be used to set an authorization header or content type to tell the server which format the ```Lua local function handle_response(self, id, response) print(response.status, response.response) end -- send some form data local headers = { ["Content-Type"] = "application/x-www-form-urlencoded" } local body = "key1=value1&key2=value2" http.request("https://www.myserver.com/post", "POST", handle_response, headers, body) -- send some json encoded data local headers = { ["Content-Type"] = "application/json" } local body = json.encode({ key1 = value1, key2 = value2 }) http.request("https://www.myserver.com/post", "POST", handle_response, headers, body) -- request some data which requires authorization to access local token = ... -- generate an access token (JWT, OAuth etc) local headers = { ["Authorization"] = "Bearer " .. token } http.request("https://www.myserver.com/content", "GET", handle_response, headers) ``` Defold will automatically set a couple of request headers: * `If-None-Match: ` will be set with the ETag of any previously cached response. * `Transfer-Encoding: chunked` will be set if the request body is larger than 16384 bytes. * `Content-Length` will be set with the size of the request body (unless the request is chunked). * `Range: bytes=-` will be set if requesting a partial response, for instance when [streaming sounds](/sound-streaming#sound-streaming). ### Response headers The server response may contain one or more response headers. These are available on the `response` table: ```lua local function handle_response(self, id, response) for header,value in pairs(response.headers) do print(header, value) end end http.request("https://www.defold.com", "GET", handle_response) ``` ### HTTP Proxy It is sometimes desirable to send a request through a proxy server. This can be done by specifying a proxy server to use when connecting to the destination server. When a proxy is used the connection to the destination server is established using an a HTTP tunnel through the proxy. The HTTP tunnel is established using the CONNECT HTTP method. Example: ```lua -- connect to www.defold.com via localhost proxy on port 8888 local url = "https://www.defold.com:443" local method = "GET" local headers = {} local post_data = nil local options = { proxy = "https://127.0.0.1:8888" } http.request(url, method, function(self, id, response) pprint(response) end, headers, post_data, options) ``` ### API Reference Refer to the [API reference](https://defold.com/ref/http/) to learn more. ### Extensions An alternative HTTP request implementation can be found in the [TinyHTTP extension](https://defold.com/assets/tinyhttp/). ## Socket connections {#manuals:socket-connections} Defold includes the [LuaSocket library](https://lunarmodules.github.io/luasocket/) for creating TCP and UDP socket connections. Example of how to create a socket connection, sending some data and reading a response: ```Lua local client = socket.tcp() client:connect("127.0.0.1", 8123) client:settimeout(0) client:send("foobar") local response = client:receive("*l") ``` This will create a TCP socket, connect it to IP 127.0.0.1 (localhost) and port 8123. It will set timeout to 0 to make the socket non-blocking and it will send the string "foobar" over the socket. It will also read a line of data (bytes ending with a newline character) from the socket. Note that the above example doesn't contain any kind of error handling. ### API Reference and examples Refer to the [API reference](https://defold.com/ref/socket/) to learn more about the functionality available via LuaSocket. The [official LuaSocket documentation](https://lunarmodules.github.io/luasocket/) also contains many examples of how to work with the library. There is also some examples and helper modules in the [DefNet library](https://github.com/britzl/defnet/). # Game services {#manuals:online-services} Using HTTP requests and socket connections allows you to connect to and interact with thousands of different services on the internet, but in most cases there's more to it than simply making an HTTP request. You usually need to use some kind of authentication, the request data may need to be formatted in a certain way and the response may need to be parsed before it can be used. This can of course be done manually by you but there are also extensions and libraries to take care of this sort of thing for you. Below you'll find a list of some extensions that can be used to more easily interact with specific backend services: ## General purpose * [Colyseus](https://defold.com/assets/colyseus/) - Multiplayer game client * [Nakama](https://defold.com/assets/nakama/) - Add authentication, matchmaking, analytics, cloud save, multiplayer, chat and more to your game * [Photon Realtime](https://defold.com/assets/photon-realtime/) - Photon Realtime offers scalable solutions for essential features such as authentication, matchmaking, and fast, reliable communication. * [PlayFab](https://defold.com/assets/playfabsdk/) - Add authentication, matchmaking, analytics, cloud save and more to your game * [AWS SDK](https://github.com/britzl/aws-sdk-lua) - Use Amazon Web Services from within your game ## Authentication, leaderboards, achievements * [Google Play Game Services](https://defold.com/assets/googleplaygameservices/) - Use Google Play Game Services to authenticate and use cloud save in your game * [Steamworks](https://defold.com/assets/steamworks/) - Add Steam support to your game * [Apple GameKit Game Center](https://defold.com/assets/gamekit/) ## Analytics * [Firebase Analytics](https://defold.com/assets/googleanalyticsforfirebase/) - Add Firebase Analytics to your game * [Game Analytics](https://gameanalytics.com/docs/item/defold-sdk) - Add GameAnalytics to your game * [Google Analytics](https://defold.com/assets/gameanalytics/) - Add Google Analytics to your game Check the [Asset Portal](https://www.defold.com/assets/) for even more extensions! # Render {#manuals:render} Every object that is shown on screen by the engine: sprites, models, tiles, particles or GUI nodes, are drawn by a renderer. At the heart of the renderer is a render script that controls the render pipeline. By default, every 2D object is drawn with the correct bitmap with the specified blending and at the correct Z depth---so you might not have to ever think about rendering beyond ordering and simple blending. For most 2D games, the default pipeline functions well, but your game might have special requirements. If that is the case, Defold allows you to write a tailor-made rendering pipeline. ### Render pipeline - What, when and where? The render pipeline controls what to render, when to render it and also where to render it. What to render is controlled by [render predicates](#render-predicates). When to render a predicate is controlled in the [render script](#the-render-script) and where to render a predicate is controlled by the [view projection](#default-view-projection). The render pipeline can also cull the graphics, drawn by a render predicate, which lies outside of a defined bounding box or frustum. This process is called frustum culling. ## The default render The render file contains a reference to the current render script as well as custom materials that should be made available in the render script (use with [`render.enable_material()`](https://defold.com/ref/render/#render.enable_material)) At the heart of the rendering pipeline is the _render script_. This is a Lua script with the functions `init()`, `update()` and `on_message()` and it is primarily used to interact with the underlying graphics API. The render script has a special place in the lifecycle of your game. Details can be found in the [Application lifecycle documentation](#manuals:application-lifecycle). In the "Builtins" folder of your projects you can find the default render resource ("default.render") and the default render script ("default.render_script"). To set up a custom renderer: 1. Copy the files "default.render" and "default.render_script" to a location in your project hierarchy. You can, of course, create a render script from scratch but it is a good idea to start with a copy of the default script, especially if you are new to Defold and/or graphics programming. 2. Edit your copy of the "default.render" file and change the *Script* property to refer to your copy of the render script. 3. Change the *Render* property (under *bootstrap*) in the *game.project* settings file to refer to your copy of the "default.render" file. ## Render predicates To be able to control the draw order of objects, you create render _predicates_. A predicate declares what should be drawn based on a selection of material _tags_. Each object that is drawn onto the screen has a material attached to it that controls how the object should be drawn to the screen. In the material, you specify one or more _tags_ that should be associated with the material. In your render script, you can then create a *render predicate* and specify which tags should belong to that predicate. When you tell the engine to draw the predicate, each object with a material containing all of the tags specified for the predicate will be drawn. ``` Sprite 1 Sprite 2 Sprite 3 Sprite 4 Material A Material A Material B Material C outlined outlined greyscale outlined tree tree tree house ``` ```lua -- a predicate matching all sprites with tag "tree" local trees = render.predicate({"tree"}) -- will draw Sprite 1, 2 and 3 render.draw(trees) -- a predicate matching all sprites with tag "outlined" local outlined = render.predicate({"outlined"}) -- will draw Sprite 1, 2 and 4 render.draw(outlined) -- a predicate matching all sprites with tags "outlined" AND "tree" local outlined_trees = render.predicate({"outlined", "tree"}) -- will draw Sprite 1 and 2 render.draw(outlined_trees) ``` A detailed description on how materials work can be found in the [Material documentation](#manuals:material). ## Default view projection The default render script is configured to use an orthographic projection suitable for 2D games. It provides three different orthographic projections: `Stretch` (default), `Fixed Fit` and `Fixed`. As an alternative to the orthographic projections in the default render script you also have the option to use the projection matrix provided by a camera component. ### Stretch projection The stretch projection will always draw an area of your game that is equal to the dimensions set in *game.project*, even when the window is resized. If the aspect ratio changes it will result in game content being stretched either vertically or horizontally: *Stretch projection with original window size* *Stretch projection with the window stretched horizontally* The stretch projection is the default projection but if you have changed from it and need to switch back you do it by sending a message to the render script: ```lua msg.post("@render:", "use_stretch_projection", { near = -1, far = 1 }) ``` ### Fixed fit projection Just like the stretch projection the fixed fit projection will always show an area of the game that is equal to the dimensions set in *game.project*, but if the window is resized and the aspect ratio changes the game content will retain the original aspect ratio and additional game content will be shown vertically or horizontally: *Fixed fit projection with original window size* *Fixed fit projection with the window stretched horizontally* *Fixed fit projection with the window reduced to 50% of original size* You enable the fixed fit projection by sending a message to the render script: ```lua msg.post("@render:", "use_fixed_fit_projection", { near = -1, far = 1 }) ``` ### Fixed projection The fixed projection will retain the original aspect ratio and render your game content with a fixed zoom level. This means that it if the zoom level is set to something other than 100% it will show more or less than the area of the game defined by the dimensions in *game.project*: *Fixed projection with zoom set to 2* *Fixed projection with zoom set to 0.5* *Fixed projection with zoom set to 2 and window reduced to 50% of original size* You enable the fixed projection by sending a message to the render script: ```lua msg.post("@render:", "use_fixed_projection", { near = -1, far = 1, zoom = 2 }) ``` ### Camera projection When using the default render script and there are enabled [Camera components](#manuals:camera) available in the project, they will take precedence over any other view / projections set in the render script. To read more about how to work with camera components in render scripts, please consult the [Camera documentation](#manuals:camera). Orthographic cameras support an `Orthographic Mode` that controls how the camera adapts to the window: - `Fixed` uses the camera’s `Orthographic Zoom` value. - `Auto Fit` (contain) keeps the full design area visible. - `Auto Cover` (cover) fills the window and may crop. You can switch modes in the Editor or at runtime via the Camera API: ```lua -- Use auto-fit behavior with an orthographic camera camera.set_orthographic_mode("main:/go#camera", camera.ORTHO_MODE_AUTO_FIT) -- Query current mode local mode = camera.get_orthographic_mode("main:/go#camera") ``` ## Frustum culling The render API in Defold lets developers perform something called frustum culling. When frustum culling is enabled any graphics that lies outside of a defined bounding box or frustum will be ignored. In a large game world where only a portion is visible at a time, frustum culling can dramatically reduce the amount of data that needs to be sent to the GPU for rendering, thus increasing performance and saving battery (on mobile devices). It is common to use the view and projection of the camera to create the bounding box. The default render script uses the view and projection (from the camera) to calculate a frustum. Frustum culling is implemented in the engine per component type. Current status (Defold 1.9.0): | Component | Supported | |-------------|-----------| | Sprite | YES | | Model | YES | | Mesh | YES (1) | | Label | YES | | Spine | YES | | Particle fx | NO | | Tilemap | YES | | Rive | NO | 1 = Mesh bounding box needs to be set by the developer. [Learn more](#manuals:mesh). ## Coordinate systems When components are rendered you usually talk of in which coordinate system the components are rendered. In most games you have some components drawn in world space and some in screen space. GUI components and their nodes are usually drawn in the screen space coordinate, with the bottom left corner of the screen having coordinate (0,0) and the top right corner is (screen width, screen height). The screen space coordinate system is never offset or in some other way translated by a camera. This will keep the GUI nodes always drawn on screen regardless of how the world is rendered. Sprites, tilemaps and other components used by game objects that exist in your game world are usually drawn in the world space coordinate system. If you make no modifications to your render script and use no camera component to change the view projection this coordinate system is the same as the screen space coordinate system, but as soon as you add a camera and either move it around or change the view projection the two coordinate systems will deviate. When the camera is moving the lower left corner of the screen will be offset from (0, 0) so that other parts of the world is rendered. If the projection changes the coordinates will be both translated (ie offset from 0, 0) and modified by a scale factor. ## The render script Below is the code for a custom render script that is a slightly modified version of the built-in one. init() : The function `init()` is used to set up the predicates, the view and clear color. These variables will be used during the actual rendering. ```lua function init(self) -- Define the render predicates. Each predicate is drawn by itself and -- that allows us to change the state of OpenGL between the draws. self.predicates = create_predicates("tile", "gui", "text", "particle", "model") -- Create and fill data tables will be used in update() local state = create_state() self.state = state local camera_world = create_camera(state, "camera_world", true) init_camera(camera_world, get_stretch_projection) local camera_gui = create_camera(state, "camera_gui") init_camera(camera_gui, get_gui_projection) update_state(state) end ``` update() : The `update()` function is called once each frame. Its function is to perform the actual drawing by calling the underlying OpenGL ES APIs (OpenGL Embedded Systems API). To properly understand what's going on in the `update()` function, you need to understand how OpenGL works. There are many great resources on OpenGL ES available. The official site is a good starting place. You find it at https://www.khronos.org/opengles/ This example contains the setup necessary to draw 3D models. The `init()` function defined a `self.predicates.model` predicate. Elsewhere a material with the tag "model" has been created. There are also some model components that use the material: ```lua function update(self) local state = self.state if not state.valid then if not update_state(state) then return end end local predicates = self.predicates -- clear screen buffers -- render.set_depth_mask(true) render.set_stencil_mask(0xff) render.clear(state.clear_buffers) local camera_world = state.cameras.camera_world render.set_viewport(0, 0, state.window_width, state.window_height) render.set_view(camera_world.view) render.set_projection(camera_world.proj) -- render models -- render.set_blend_func(render.BLEND_SRC_ALPHA, render.BLEND_ONE_MINUS_SRC_ALPHA) render.enable_state(render.STATE_CULL_FACE) render.enable_state(render.STATE_DEPTH_TEST) render.set_depth_mask(true) render.draw(predicates.model_pred) render.set_depth_mask(false) render.disable_state(render.STATE_DEPTH_TEST) render.disable_state(render.STATE_CULL_FACE) -- render world (sprites, tilemaps, particles etc) -- render.set_blend_func(render.BLEND_SRC_ALPHA, render.BLEND_ONE_MINUS_SRC_ALPHA) render.enable_state(render.STATE_DEPTH_TEST) render.enable_state(render.STATE_STENCIL_TEST) render.enable_state(render.STATE_BLEND) render.draw(predicates.tile) render.draw(predicates.particle) render.disable_state(render.STATE_STENCIL_TEST) render.disable_state(render.STATE_DEPTH_TEST) -- debug render.draw_debug3d() -- render GUI -- local camera_gui = state.cameras.camera_gui render.set_view(camera_gui.view) render.set_projection(camera_gui.proj) render.enable_state(render.STATE_STENCIL_TEST) render.draw(predicates.gui, camera_gui.frustum) render.draw(predicates.text, camera_gui.frustum) render.disable_state(render.STATE_STENCIL_TEST) end ``` So far this is a simple and straightforward render script. It draws in the same manner every single frame. However, it is sometimes desirable to be able to introduce state into the render script and perform different operations depending on the state. It may also be desirable to communicate with the render script from other parts of the game code. on_message() : A render script can define an `on_message()` function and receive messages from other parts of your game or app. A common case where an external component sends information to the render script is the _camera_. A camera component that has acquired camera focus will automatically send its view and projection to the render script each frame. This message is named `"set_view_projection"`: ```lua local MSG_CLEAR_COLOR = hash("clear_color") local MSG_WINDOW_RESIZED = hash("window_resized") local MSG_SET_VIEW_PROJ = hash("set_view_projection") function on_message(self, message_id, message) if message_id == MSG_CLEAR_COLOR then -- Someone sent us a new clear color to be used. update_clear_color(state, message.color) elseif message_id == MSG_SET_VIEW_PROJ then -- The camera component that has camera focus will sent set_view_projection -- messages to the @render socket. We can use the camera information to -- set view (and possibly projection) of the rendering. camera.view = message.view self.camera_projection = message.projection or vmath.matrix4() update_camera(camera, state) end end ``` However, any script of GUI script can send messages to the render script though the special `@render` socket: ```lua -- Change the clear color. msg.post("@render:", "clear_color", { color = vmath.vector4(0.3, 0.4, 0.5, 0) }) ``` ## Render Resources To pass in certain engine resources into the render script, you can add these into the `Render Resources` table in the .render file assigned to the project: Using these resources in a render script: ```lua -- "my_material" will now be used for all draw calls associated with the predicate render.enable_material("my_material") -- anything drawn by the predicate will end up in "my_render_target" render.set_render_target("my_render_target") render.draw(self.my_full_screen_predicate) render.set_render_target(render.RENDER_TARGET_DEFAULT) render.disable_material() -- bind the render target result texture to whatever is getting rendered via the predicate render.enable_texture(0, "my_render_target", render.BUFFER_COLOR0_BIT) render.draw(self.my_tile_predicate) ``` Defold currently only supports `Materials` and `Render Targets` as referenced render resources, but over time more resource types will be supported by this system. ## Texture handles Textures in Defold are represented internally as a handle, which essentially equates to a number that should uniquely identify a texture object anywhere in the engine. This means that you can bridge the gameobject world with the rendering world by passing these handles between the render system and a gameobject script. For example, a script can create a dynamic texture in a script attached to a gameobject and send this to the renderer to be used as a global texture in a draw command. In a `.script` file: ```lua local my_texture_resource = resource.create_texture("/my_texture.texture", tparams) -- note: my_texture_resource is a hash to the resource path, which can't be used as a handle! local my_texture_handle = resource.get_texture_info(my_texture_resource) -- my_texture_handle contains information about the texture, such as width, height and so on -- it does also contain the handle, which is what we are after msg.post("@render:", "set_texture", { handle = my_texture_handle.handle }) ``` In a .render_script file: ```lua function on_message(self, message_id, message) if message_id == hash("set_texture") then self.my_texture = message.handle end end function update(self) -- bind the custom texture to the draw state render.enable_texture(0, self.my_texture) -- do drawing.. end ``` There is currently no way of changing which texture a resource should point to, you can only use raw handles like this in the render script. ## Supported graphics APIs The Defold render script API translates render operations into the following graphics APIs: | System | Graphics API | Note | |----------|----------------------------|--------------------------| | macOS | OpenGL 3.3 or Metal | Vulkan via MoltenVK | | Windows | OpenGL 3.3 or Vulkan 1.1 | | | Linux | OpenGL 3.3 or Vulkan 1.1 | | | Android | OpenGLES 3.0 or Vulkan 1.1 | Fallback to OpenGLES 2.0 | | iOS | OpenGLES 3.0 or Metal | Vulkan via MoltenVK | | HTML5 | WebGL 2.0 or WebGPU | Fallback to WebGL 1.0 | ## System messages `"set_view_projection"` : This message is sent from camera components that has acquired camera focus. `"window_resized"` : The engine will send this message on changes of the window size. You can listen to this message to alter rendering when the target window size changes. On desktop this means that the actual game window has been resized and on mobile devices this message is sent whenever an orientation change happens. ```lua local MSG_WINDOW_RESIZED = hash("window_resized") function on_message(self, message_id, message) if message_id == MSG_WINDOW_RESIZED then -- The window was resized. message.width and message.height contain the new dimensions. ... end end ``` `"draw_line"` : Draw debug line. Use to visualize ray_casts, vectors and more. Lines are drawn with the `render.draw_debug3d()` call. ```lua -- draw a white line local p1 = vmath.vector3(0, 0, 0) local p2 = vmath.vector3(1000, 1000, 0) local col = vmath.vector4(1, 1, 1, 1) msg.post("@render:", "draw_line", { start_point = p1, end_point = p2, color = col } ) ``` `"draw_text"` : Draw debug text. Use to print debug information. The text is drawn with the built-in `always_on_top.font` font. The system font has a material with tag `debug_text` and is rendered with other text in the default render script. ```lua -- draw a text message local pos = vmath.vector3(500, 500, 0) msg.post("@render:", "draw_text", { text = "Hello world!", position = pos }) ``` The visual profiler accessible through the `"toggle_profile"` message sent to the `@system` socket is not part of the scriptable renderer. It is drawn separate from your render script. ## Draw calls and batching A draw call is the term used to describe the process of setting up the GPU to draw an object to the screen using a texture and a material with optional additional settings. This process is usually resource intensive and it is recommended that the number of draw calls are as few as possible. You can measure the number of the draw calls and the time it takes to render them using the [built-in profiler](#manuals:profiling). Defold will try to batch render operation to reduce the number of draw calls according to a set of rules defined below. The rules differ between GUI components and all other component types. ### Batch rules for non-GUI components Rendering is done based on z-order, from low to high. The engine will start by sorting the list of things to draw and iterate from low to high z-values. Each object in the list will be grouped into the same draw call as the previous object if the following conditions are met: * Belongs to the same collection proxy * Is of the same component type (sprite, particle fx, tilemap etc) * Uses the same texture (atlas or tile source) * Has the same material * Has the same shader constants (such as tint) This means that if two sprite components in the same collection proxy has adjacent or the same z-value (and thus comes next to each other in the sorted list), use the same texture, material and constants they will be grouped into the same draw call. ### Batch rules for GUI components Rendering of the nodes in a GUI component are done from top to bottom of the node list. Each node in the list will be grouped into the same draw call as the previous node if the following conditions are met: * Is of the same type (box, text, pie etc) * Uses the same texture (atlas or tile source) * Has the same blend mode. * Has the same font (only for text nodes) * Has the same stencil settings Rendering of nodes are done per component. This means that nodes from different GUI components will not be batched. The ability to arrange nodes in hierarchies makes it easy to group nodes into manageable units. But hierarchies can effectively break batch rendering if you mix different node types. It is possible to more effectively batch GUI nodes while maintaining node hierarchies using GUI layers. You can read more about GUI layers and how they affect draw calls in the [GUI manual](#manuals:gui#layers-and-draw-calls). # Materials {#manuals:material} Materials are used to express how a graphical component (a sprite, tilemap, font, GUI node, model etc) should be rendered. A material holds _tags_, information that is used in the rendering pipeline to select objects to be rendered. It also holds references to _shader programs_ that are compiled through the available graphics driver and uploaded to the graphics hardware and run when the component is rendered each frame. * For more information on the render pipeline, see the [Render documentation](#manuals:render). * For an in depth explanation of shader programs, see the [Shader documentation](#manuals:shader). ## Creating a material To create a material, `right click` a target folder in the *Assets* browser and select `New... ▸ Material`. (You can also select `File ▸ New...` from the menu, and then select `Material`). Name the new material file and press `Ok`. The new material will open in the *Material Editor*. The material file contains the following information: Name : The identity of the material. This name is used to list the material in the *Render* resource to include it in the build. The name is also used in the render API function `render.enable_material()`. The name should be unique. Vertex Program : The vertex shader program file (*`.vp`*) to use when rendering with the material. The vertex shader program is run on the GPU for each of a component's primitive vertices. It computes the screen position of each vertex and also optionally output "varying" variables that are interpolated and input to the fragment program. Fragment Program : The fragment shader program file (*`.fp`*) to use when rendering with the material. The program runs on the GPU for each of a primitive's fragments (pixels) and its purpose is to decide the color of each fragment. This is usually done by texture lookups and calculations based on input variables (varying variables or constants). Vertex Constants : Uniforms that will be passed to the vertex shader program. See below for a list of available constants. Fragment Constants : Uniforms that will be passed to the fragment shader program. See below for a list of available constants. Samplers : You can optionally configure specific samplers in the materials file. Add a sampler, name it according to the name used in the shader program and set the wrap and filter settings to your liking. Tags : The tags associated with the material. Tags are represented in the engine as a _bitmask_ that is used by [`render.predicate()`](https://defold.com/ref/render#render.predicate) to collect components that should be drawn together. See the [Render documentation](#manuals:render) on how to do that. The maximum number of tags you can use in a project is 32. ## Attributes Shader attributes (also referred to as vertex streams, or vertex attributes), is a mechanism for how the GPU retrieves vertices from memory in order to render geometry. The vertex shader specifies a set of streams by using the `attribute` keyword and in most cases Defold produces and binds the data automatically under the hood based on the names of the streams. However, in some cases you might want to forward more data per vertex to achieve a specific effect that the engine does not produce. A vertex attribute can be configured with the following fields: Name : The attribute name. Similar to shader constants, the attribute configuration will only be used if it matches an attribute specified in the vertex program. Semantic type : A semantic type indicates the semantic meaning of *what* the attribute is and/or *how* it should be shown in the editor. For example, specifying an attribute with a `SEMANTIC_TYPE_COLOR` will show a color picker in the editor, while the data will still be passed in as-is from the engine to the shader. - `SEMANTIC_TYPE_NONE` The default semantic type. Does not have any other effect on the attribute other than passing the material data for the attribute directly to the vertex buffer (default) - `SEMANTIC_TYPE_POSITION` Produces per-vertex position data for the attribute. Can be used together with coordinate space to tell the engine how the positions will be calculated - `SEMANTIC_TYPE_TEXCOORD` Produces per-vertex texture coordinates for the attribute - `SEMANTIC_TYPE_PAGE_INDEX` Produces per-vertex page indices for the attribute - `SEMANTIC_TYPE_COLOR` Affects how the editor interprets the attribute. If an attribute is configured with a color semantic, a color picked widget will be shown in the inspector - `SEMANTIC_TYPE_NORMAL` Produces per-vertex normal data for the attribute - `SEMANTIC_TYPE_TANGENT` Produces per-vertex tangent data for the attribute - `SEMANTIC_TYPE_WORLD_MATRIX` Produces per-vertex world matrix data for the attribute - `SEMANTIC_TYPE_NORMAL_MATRIX` Produces per-vertex normal matrix data for the attribute - `SEMANTIC_TYPE_TEXTURE_TRANSFORM_2D` Produces a per-vertex 3x3 texture transform matrix for the attribute. For particle components, the engine provides a matrix that transforms coordinates into atlas space for the image property on the component. For sprite components, the engine provides a matrix for each image the component is using (when using multi-texturing). For model components, an identity matrix is provided. Data type : The data type of the backing data for the attribute. - `TYPE_BYTE` Signed 8-bit byte values - `TYPE_UNSIGNED_BYTE` Unsigned 8-bit byte values - `TYPE_SHORT` Signed 16-bit short values - `TYPE_UNSIGNED_SHORT` Unsigned 16-bit short values - `TYPE_INT` Signed integer values - `TYPE_UNSIGNED_INT` Unsigned integer values - `TYPE_FLOAT` Floating point values (default) Normalize : If true, the attribute values will be normalized by the GPU driver. This can be useful when you don't need full precision, but want to calculate something without knowing the specific limits. E.g a color vector typically only need byte values of 0..255 while still being treated as a 0..1 value in the shader. Coordinate space : Some semantic types support supplying data in different coordinate spaces. To implement a billboarding effect with sprites, you typically want a position attribute in local space as well as a fully transformed position in world space for most effective batching. Vector type : The vector type of the attribute. - `VECTOR_TYPE_SCALAR` Single scalar value - `VECTOR_TYPE_VEC2` 2D vector - `VECTOR_TYPE_VEC3` 3D vector - `VECTOR_TYPE_VEC4` 4D vector (default) - `VECTOR_TYPE_MAT2` 2D matrix - `VECTOR_TYPE_MAT3` 3D matrix - `VECTOR_TYPE_MAT4` 4D matrix Step function : Specifies how the attribute data should be presented to the vertex function. This is only relevant for instancing. - `Vertex` Once per vertex, e.g a position attribute will typically be given to the vertex function per vertex in the mesh (default) - `Instance` Once per instance, e.g a world matrix attribute will typically be given to the vertex function once per instance Value : The value of the attribute. Attribute values can be overridden on a per-component basis, but otherwise this will act as the default value of the vertex attribute. Note: for *default* attributes (position, texture coordinates and page indices) the value will be ignored. Custom attributes can also be used to trim memory footprint on both CPU and GPU by reconfiguring the streams to use a smaller data type, or a different element count. ### Default attribute semantics The material system will assign a default semantic type automatically based on the name of the attribute in run-time for a specific set of names: - `position` - semantic type: `SEMANTIC_TYPE_POSITION` - `texcoord0` - semantic type: `SEMANTIC_TYPE_TEXCOORD` - `texcoord1` - semantic type: `SEMANTIC_TYPE_TEXCOORD` - `page_index` - semantic type: `SEMANTIC_TYPE_PAGE_INDEX` - `color` - semantic type: `SEMANTIC_TYPE_COLOR` - `normal` - semantic type: `SEMANTIC_TYPE_NORMAL` - `tangent` - semantic type: `SEMANTIC_TYPE_TANGENT` - `mtx_world` - semantic type: `SEMANTIC_TYPE_WORLD_MATRIX` - `mtx_normal` - semantic type: `SEMANTIC_TYPE_NORMAL_MATRIX` - `mtx_texture_transform_2d` - semantic type: `SEMANTIC_TYPE_TEXTURE_TRANSFORM_2D` If you have entries for these attributes in the material, the default semantic type will be overridden with whatever you have configured in the material editor. ### Setting custom vertex attribute data Similar to user defined shader constants, you can also update vertex attributes in runtime by calling go.get, go.set and go.animate: ```lua go.set("#sprite", "tint", vmath.vector4(1,0,0,1)) go.animate("#sprite", "tint", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(1,0,0,1), go.EASING_LINEAR, 2) ``` There are some caveats to updating the vertex attributes however, whether or not a component can use the value depends on the semantic type of the attribute. For example, a sprite component supports the `SEMANTIC_TYPE_POSITION` so if you update an attribute that has this semantic type, the component will ignore the overridden value since the semantic type dictates that the data should always be produced by the sprites position. In cases where that a vertex attribute is either a scalar or a vector type other than a `Vec4` you can still set the data using `go.set`: ```lua -- The last two components in the vec4 will not be used! go.set("#sprite", "sprite_position_2d", vmath.vector4(my_x,my_y,0,0)) go.animate("#sprite", "sprite_position_2d", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(1,2,0,0), go.EASING_LINEAR, 2) ``` The same is true for matrix attributes, if the attribute is a matrix type other than a `Mat4` you can still set the data using `go.set`. ### Examples of using custom vertex attributes Using a texture transform attribute to convert UV coordinates to atlas space: ```glsl #version 140 in vec3 position; in vec4 texcoord0; in mat3 texture_transform_2d; out vec2 var_texcoord0; void main() { // Extract position from the transform vec2 atlas_pos = texture_transform_2d[2].xy; // Extract the scale from the transform vec2 atlas_size = vec2( length(texture_transform_2d[0].xy), length(texture_transform_2d[1].xy) ); // convert to local UV (0..1) vec2 localUV = (texcoord0 - atlas_pos) / atlas_size; // Alternatively, if the UV coordinates already are in the 0..1 range, // you can transform into atlas space directly by multiplying the transform: vec2 transformedUv = texture_transform_2d * texcoord0; // Pass the value into the fragment shader var_texcoord0 = localUV; // ... rest of vertex shader } ``` ### Instancing Instancing is a technique used to efficiently draw multiple copies of the same object in a scene. Instead of creating a separate copy of the object each time it's used, instancing allows the graphics engine to create a single object and then reuse it multiple times. For example, in a game with a large forest, instead of creating a separate tree model for each tree, instancing allows you to create one tree model and then place it hundreds or thousands of times with different positions and scales. The forest can now be rendered with a single draw call instead of individual draw calls for each tree. Instancing is currently only available for Model components. Instancing is enabled automatically when possible. Defold heavily relies on batching the draw state as much as possible - for instancing to work some requirements must be met: - The same material must be used for all instances. Instancing will still work if a custom material has been set by `render.enable_material`) - The material must be configured to use the 'local' vertex space - The material must have at least one vertex attribute that is repeated per instance - Constant values must be the same for all instances. Constant values can be put into custom vertex attributes or some other backing method instead (e.g a texture) - Shader resources, such as textures or storage buffers, must be the same for all instances Configuring a vertex attribute to be repeated per instance requires that the `Step function` is set to `Instance`. This is done automatically for certain semantic types based on name (see the `Default attribute semantics` table above), but it can also be set manually in the material editor by setting the `Step function` to `Instance`. As a simple example, the following scene has four game objects with a model component each: The material is configured as such, with a single custom vertex attribute that is repeated per instance: The vertex shader has multiple per-instance attributes specified: ```glsl // Per vertex attributes attribute highp vec4 position; attribute mediump vec2 texcoord0; attribute mediump vec3 normal; // Per instance attributes attribute mediump mat4 mtx_world; attribute mediump mat4 mtx_normal; attribute mediump vec4 instance_color; ``` Note that the `mtx_world` and `mtx_normal` will be configured to use the step function `Instance` by default. This can be changed in the material editor by adding an entry for them and setting the `Step function` to `Vertex`, which will make the attribute be repeated per vertex instead of per instance. To verify that the instancing works in this case, you can look at the web profiler. In this case, since the only thing that changes between the instances of the box is the per-instance attributes, it can be rendered with a single draw call: #### Backwards compatibility On OpenGL based graphics adapters, instancing requires at least OpenGL 3.1 for desktop and OpenGL ES 3.0 for mobile. This means that very old devices that are using OpenGL ES2 or older OpenGL versions might not support instancing. In this case, rendering will still work by default without any special care from the developer, but it may not be as performant as if actual instancing was used. Currently, there is no way of detecting if instancing is supported or not, but this functionality will be added in the future so that a cheaper material can be used, or things like foliage or clutter that typically would be good candidates for instancing, could be skipped completely. ## Vertex and fragment constants Shader constants, or "uniforms" are values that are passed from the engine to vertex and fragment shader programs. To use a constant you define it in the material file as either a *Vertex Constant* property or a *Fragment Constant* property. Corresponding `uniform` variables need to be defined in the shader program. The following constants can be set in a material: `CONSTANT_TYPE_WORLD` : The world matrix. Use to transform vertices into world space. For some component types, the vertices are already in world space when they arrive to the vertex program (due to batching). In those cases multiplying with the world matrix in the shader will yield the wrong results. `CONSTANT_TYPE_VIEW` : The view matrix. Use to transform vertices to view (camera) space. `CONSTANT_TYPE_PROJECTION` : The projection matrix. Use to transform vertices to screen space. `CONSTANT_TYPE_VIEWPROJ` : A matrix with the view and projection matrices already multiplied. `CONSTANT_TYPE_WORLDVIEW` : A matrix with the world and view matrices already multiplied. `CONSTANT_TYPE_WORLDVIEWPROJ` : A matrix with the world, view and projection matrices already multiplied. `CONSTANT_TYPE_NORMAL` : A matrix to compute normal orientation. The world transform might include non-uniform scaling, which breaks the orthogonality of the combined world-view transform. The normal matrix is used to avoid issues with the direction when transforming normals. (The normal matrix is the transpose inverse of the world-view matrix). `CONSTANT_TYPE_USER` : A vector4 constant that you can use for any custom data you want to pass into your shader programs. You can set the initial value of the constant in the constant definition, but it is mutable through the functions [go.set()](https://defold.com/ref/stable/go/#go.set) / [go.animate()](https://defold.com/ref/stable/go/#go.animate). You can also retrieve the value with [go.get()](https://defold.com/ref/stable/go/#go.get). Changing a material constant of a single component instance [breaks render batching and will result in additional draw calls](#manuals:render). Example: ```lua go.set("#sprite", "tint", vmath.vector4(1,0,0,1)) go.animate("#sprite", "tint", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(1,0,0,1), go.EASING_LINEAR, 2) ``` `CONSTANT_TYPE_USER_MATRIX4` : A matrix4 constant that you can use for any custom data you want to pass into your shader programs. You can set the initial value of the constant in the constant definition, but it is mutable through the functions [go.set()](https://defold.com/ref/stable/go/#go.set) / [go.animate()](https://defold.com/ref/stable/go/#go.animate). You can also retrieve the value with [go.get()](https://defold.com/ref/stable/go/#go.get). Changing a material constant of a single component instance [breaks render batching and will result in additional draw calls](#manuals:render). Example: ```lua go.set("#sprite", "m", vmath.matrix4()) ``` In order for a material constant of type `CONSTANT_TYPE_USER` or `CONSTANT_TYPE_MATRIX4` to be available using `go.get()` and `go.set()` it has to be used in the shader program. If the constant is defined in the material but not used in the program it will be removed from the material and it will not be available at run-time. ## Samplers Samplers are used to sample the color information from a texture (a tile source or atlas). The color information can then be used for calculations in the shader program. Sprite, tilemap, GUI and particle effect components automatically gets a `sampler2D` set. The first declared `sampler2D` in the shader program is automatically bound to the image referenced in the graphics component. Therefore there is currently no need to specify any samplers in the materials file for those components. Furthermore, those component types currently only support a single texture. (If you need multiple textures in a shader, you can use [`render.enable_texture()`](https://defold.com/ref/render/#render.enable_texture) and set texture samplers manually from your render script.) ```glsl -- mysprite.fp varying mediump vec2 var_texcoord0; uniform lowp sampler2D MY_SAMPLER; void main() { gl_FragColor = texture2D(MY_SAMPLER, var_texcoord0.xy); } ``` You can specify a component's sampler settings by adding the sampler by name in the materials file. If you don't set up your sampler in the materials file, the global *graphics* project settings are used. For model components, you need to specify your samplers in the material file with the settings you want. The editor will then allow you to set textures for any model component that use the material: ```glsl -- mymodel.fp varying mediump vec2 var_texcoord0; uniform lowp sampler2D TEXTURE_1; uniform lowp sampler2D TEXTURE_2; void main() { lowp vec4 color1 = texture2D(TEXTURE_1, var_texcoord0.xy); lowp vec4 color2 = texture2D(TEXTURE_2, var_texcoord0.xy); gl_FragColor = color1 * color2; } ``` ## Sampler settings Name : The name of the sampler. This name should match the `sampler2D` declared in the fragment shader. Wrap U/W : The wrap mode for the U and V axes: - `WRAP_MODE_REPEAT` will repeat texture data outside the range [0,1]. - `WRAP_MODE_MIRRORED_REPEAT` will repeat texture data outside the range [0,1] but every second repetition is mirrored. - `WRAP_MODE_CLAMP_TO_EDGE` will set texture data for values greater than 1.0 to 1.0, and any values less than 0.0 is set to 0.0---i.e. the edge pixels will be repeated to the edge. Filter Min/Mag : The filtering for magnification and minification. Nearest filtering requires less computation than linear interpolation, but can result in aliasing artifacts. Linear interpolation often provides smoother results: - `Default` uses the default filter option specified in the `game.project` file under `Graphics` as `Default Texture Min Filter` and `Default Texture Mag Filter` . - `FILTER_MODE_NEAREST` uses the texel with coordinates nearest the center of the pixel. - `FILTER_MODE_LINEAR` sets a weighted linear average of the 2x2 array of texels that lie nearest to the center of the pixel. - `FILTER_MODE_NEAREST_MIPMAP_NEAREST` chooses the nearest texel value within an individual mipmap. - `FILTER_MODE_NEAREST_MIPMAP_LINEAR` selects the nearest texel in the two nearest best choices of mipmaps and then interpolates linearly between these two values. - `FILTER_MODE_LINEAR_MIPMAP_NEAREST` interpolates linearly within an individual mipmap. - `FILTER_MODE_LINEAR_MIPMAP_LINEAR` uses linear interpolation to compute the value in each of two maps and then interpolates linearly between these two values. Max Anisotropy : Anisotropic filtering is an advanced filtering technique that takes multiple samples, blending the results together. This setting controls the level of anisotropy for the texture samplers. If anisotropic filtering is not supported by the GPU the parameter will not do anything, and it will be set to 1 as default. ## Constants buffers When the rendering pipeline draws, it pulls constant values from a default system constants buffer. You can create a custom constants buffer to override the default constants and instead set shader program uniforms programmatically in the render script: ```lua self.constants = render.constant_buffer() -- <1> self.constants.tint = vmath.vector4(1, 0, 0, 1) -- <2> ... render.draw(self.my_pred, {constants = self.constants}) -- <3> ``` 1. Create a new constants buffer 2. Set the `tint` constant to bright red 3. Draw the predicate using our custom constants Note that the buffer's constant elements are referenced like an ordinary Lua table, but you can't iterate over the buffer with `pairs()` or `ipairs()`. # Compute programs {#manuals:compute} Compute shader support in Defold currently in *technical preview*. This means that there are some features lacking, and that the API could potentially change in the future. Compute shaders are a powerful tool for performing general-purpose computations on the GPU. They allow you to leverage the parallel processing power of the GPU for tasks such as physics simulations, image processing, and more. A compute shader operates on data stored in buffers or textures, performing operations in parallel across many GPU threads. This parallelism is what makes compute shaders so powerful for intensive computations. * For more information on the render pipeline, see the [Render documentation](#manuals:render). * For an in depth explanation of shader programs, see the [Shader documentation](#manuals:shader). ## What can I do with compute shaders? Since compute shaders are meant to be used for generic computation, there is really no limit to what you can do with them. Here are some examples what compute shaders are typically used for: Image Processing - Image filtering: Apply blurs, edge detection, a sharpen filter and so on. - Color grading: Adjust the color space of an image. Physics - Particle systems: Simulating large numbers of particles for effects like smoke, fire, and fluid dynamics. - Soft Body Physics: Simulating deformable objects like cloth and jelly. - Culling: Occlusion culling, frustum culling Procedural Generation - Terrain Generation: Creating detailed terrain using noise functions. - Vegetation and Foliage: Creating procedurally generated plants and trees. Rendering effects - Global illumination: Simulating realistic lighting by approximating the way light bounces around a scene. - Voxelization: Create a 3D voxel grid from mesh data. ## How does compute shaders work? At a high level, compute shaders work by dividing a task into many smaller tasks that can be executed simultaneously. This is achieved through the concept of `work groups` and `invocations`: Work Groups : The compute shader operates on a grid of `work groups`. Each work group contains a fixed number of invocations (or threads). The size of the work groups and the number of invocations are defined in the shader code. Invocations : Each invocation (or thread) executes the compute shader program. Invocations within a work group can share data through shared memory, allowing for efficient communication and synchronization between them. The GPU executes the compute shader by launching many invocations across multiple work groups in parallel, providing significant computational power for suitable tasks. ## Creating a compute program To create a compute program, `right click` a target folder in the *Assets* browser and select `New... ▸ Compute`. (You can also select `File ▸ New...` from the menu, and then select `Compute`). Name the new compute file and press `Ok`. The new compute will open in the *Compute Editor*. The compute file contains the following information: Compute Program : The compute shader program file (*`.cp`*) to use. The shader operates on "abstract work items", meaning that there is no fixed definition of the input and output data types. It is up to the programmer to define what the compute shader should produce. Constants : Uniforms that will be passed to the compute shader program. See below for a list of available constants. Samplers : You can optionally configure specific samplers in the materials file. Add a sampler, name it according to the name used in the shader program and set the wrap and filter settings to your liking. ## Using the compute program in Defold In contrast to materials, compute programs are not assigned to any components, and are not part of the normal render flow. A compute program must be `dispatched` in a render script to do any work. Before dispatching however, you need to make sure the render script has a reference to the compute program. Currently, the only way for a render script to know about the compute program is to add it into the .render file that holds the reference to your render script: To use the compute program, it first needs to be bound to the render context. This is done in the same way as materials: ```lua render.set_compute("my_compute") -- Do compute work here, call render.set_compute() to unbind render.set_compute() ``` While the compute constants will be automatically applied when the program is dispatched, there is no way to bind any inputs or output resources (textures, buffers and so on) to a compute program from the editor. Instead this must be done via render scripts: ```lua render.enable_texture("blur_render_target", "tex_blur") render.enable_texture(self.storage_texture, "tex_storage") ``` To run the program in the working space you have decided, you need to dispatch the program: ```lua render.dispatch_compute(128, 128, 1) -- dispatch_compute also accepts an options table as the last argument -- you can use this argument table to pass in render constants to the dispatch call local constants = render.constant_buffer() constants.tint = vmath.vector4(1, 1, 1, 1) render.dispatch_compute(32, 32, 32, {constants = constants}) ``` ### Writing data from compute programs Currently, generating any type of output from a compute program can only be done via `storage textures`. A storage texture is similar to a "regular texture" except that they support more functionality and configurability. Storage textures, as the name implies, can be used as a generic buffer that you can read and write data to from a compute program. You can then bind the same buffer to a different shader program for reading. To create a storage texture in Defold, you need to do this from a regular .script file. Render scripts does not have this functionality as dynamic textures need to be created via the resource API which is only available in regular .script files. ```lua -- In a .script file: function init(self) -- Create a texture resource like usual, but add the "storage" flag -- so it can be used as the backing storage for compute programs local t_backing = resource.create_texture("/my_backing_texture.texturec", { type = resource.TEXTURE_TYPE_IMAGE_2D, width = 128, height = 128, format = resource.TEXTURE_FORMAT_RGBA32F, flags = resource.TEXTURE_USAGE_FLAG_STORAGE + resource.TEXTURE_USAGE_FLAG_SAMPLE, }) -- get the texture handle from the resource local t_backing_handle = resource.get_texture_info(t_backing).handle -- notify the renderer of the backing texture, so it can be bound with render.enable_texture msg.post("@render:", "set_backing_texture", { handle = t_backing_handle }) end ``` ## Putting it all together ### Shader program ```glsl // compute.cp #version 450 layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; // specify the input resources uniform vec4 color; uniform sampler2D texture_in; // specify the output image layout(rgba32f) uniform image2D texture_out; void main() { // This isn't a particularly interesting shader, but it demonstrates // how to read from a texture and constant buffer and write to a storage texture ivec2 tex_coord = ivec2(gl_GlobalInvocationID.xy); vec4 output_value = vec4(0.0, 0.0, 0.0, 1.0); vec2 tex_coord_uv = vec2(float(tex_coord.x)/(gl_NumWorkGroups.x), float(tex_coord.y)/(gl_NumWorkGroups.y)); vec4 input_value = texture(texture_in, tex_coord_uv); output_value.rgb = input_value.rgb * color.rgb; // Write the output value to the storage texture imageStore(texture_out, tex_coord, output_value); } ``` ### Script component ```lua -- In a .script file -- Here we specify the input texture that we later will bind to the -- compute program. We can assign this texture to a model component, -- or enable it to the render context in the render script. go.property("texture_in", resource.texture()) function init(self) -- Create a texture resource like usual, but add the "storage" flag -- so it can be used as the backing storage for compute programs local t_backing = resource.create_texture("/my_backing_texture.texturec", { type = resource.TEXTURE_TYPE_IMAGE_2D, width = 128, height = 128, format = resource.TEXTURE_FORMAT_RGBA32F, flags = resource.TEXTURE_USAGE_FLAG_STORAGE + resource.TEXTURE_USAGE_FLAG_SAMPLE, }) local textures = { texture_in = resource.get_texture_info(self.texture_in).handle, texture_out = resource.get_texture_info(t_backing).handle } -- notify the renderer of the input and output textures msg.post("@render:", "set_backing_texture", textures) end ``` ### Render script ```lua -- respond to the message "set_backing_texture" -- to set the backing texture for the compute program function on_message(self, message_id, message) if message_id == hash("set_backing_texture") then self.texture_in = message.texture_in self.texture_out = message.texture_out end end function update(self) render.set_compute("compute") -- We can bind textures to specific named constants render.enable_texture(self.texture_in, "texture_in") render.enable_texture(self.texture_out, "texture_out") render.set_constant("color", vmath.vector4(0.5, 0.5, 0.5, 1.0)) -- Dispatch the compute program as many times as we have pixels. -- This constitutes our "working group". The shader will be invoked -- 128 x 128 x 1 times, or once per pixel. render.dispatch_compute(128, 128, 1) -- when we are done with the compute program, we need to unbind it render.set_compute() end ``` ## Compatibility Defold currently supports compute shaders in the following graphics adapters: - Vulkan - Metal (via MoltenVK) - OpenGL 4.3+ - OpenGL ES 3.1+ There is currently no way to check if the running client supports compute shaders. This means that there is no guarantee that the client supports running compute shaders if the graphics adapter is OpenGL, or OpenGL ES based. Vulkan and Metal support compute shaders from version 1.0. To use Vulkan, you need to create a custom manifest and select Vulkan as the backend. # Shaders {#manuals:shader} Shader programs are at the core of graphics rendering. They are programs written in a C-like language called GLSL (GL Shading Language) that the graphics hardware run to perform operations on either the underlying 3D data (the vertices) or the pixels that end up on the screen (the "fragments"). Shaders are used for drawing sprites, lighting 3D models, creating full screen post effects and much, much more. This manual describes how Defold's rendering pipeline interfaces with GPU shaders. In order to create shaders for your content, you also need to understand the concept of materials, as well as how the render pipeline works. * See the [Render manual](#manuals:render) for details on the render pipeline. * See the [Material manual](#manuals:material) for details on materials. * See the [Compute manual](#manuals:compute) for details on compute programs. Specifications of OpenGL ES 2.0 (OpenGL for Embedded Systems) and OpenGL ES Shading Language can be found at [Khronos OpenGL Registry](https://www.khronos.org/registry/gles/). Observe that on desktop computers it is possible to write shaders using features not available on OpenGL ES 2.0. Your graphics card driver may happily compile and run shader code that will not work on mobile devices. ## Concepts Vertex shader : A vertex shader cannot create or delete vertices, only change the position of a vertex. Vertex shaders are commonly used to transform the positions of vertices from the 3D world space into 2D screen space. The input of a vertex shader is vertex data (in the form of `attributes`) and constants (`uniforms`). Common constants are the matrices necessary to transform and project the position of a vertex to screen space. The output of the vertex shader is the computed screen position of the vertex (`gl_Position`). It is also possible to pass data from the vertex shader to the fragment shader through `varying` variables. Fragment shader : After the vertex shader is done, it is the job of the fragment shader to decide the coloring of each fragment (or pixel) of the resulting primitives. The input of a fragment shader is constants (`uniforms`) as well as any `varying` variables that has been set by the vertex shader. The output of the fragment shader is the color value for the particular fragment (`gl_FragColor`). Compute shader : A compute shader is a general purpose shader that can be used to perform any type of work on a GPU. It is not part of the graphics pipeline at all, compute shaders run in a separate execution context and is not dependent on input from any other shader. The input of a compute shader is constant buffers (`uniforms`), texture images (`image2D`), samplers (`sampler2D`) and storage buffers (`buffer`). The output of the compute shader is not explicitly defined, there is no specific output that needs to be produced as opposed to the vertex and the fragment shaders. As compute shaders are generic, it is up to the programmer to define what type of result the compute shader should produce. World matrix : The vertex positions of a model's shape are stored relative to the model's origin. This is called "model space". The game world, however, is a "world space" where the position, orientation and scale of each vertex is expressed relative to the world origin. By keeping these separate the game engine is able to move, rotate and scale each model without destroying the original vertex values stored in the model component. When a model is placed in the game world the model's local vertex coordinates must be translated to world coordinates. This translation is done by a *world transform matrix*, which tells what translation (movement), rotation and scale should be applied to a model's vertices to be correctly placed in the game world's coordinate system. View and projection matrix : In order to put the vertices of the game world onto the screen, each matrix' 3D coordinates is first translated into coordinates relative to the camera. This is done with a _view matrix_. Secondly, the vertices are projected onto the 2D screen space with a _projection matrix_: Attributes : A value associated with an individual vertex. Attributes are passed to the shader by the engine and if you want to access an attribute you just declare it in your shader program. Different component types have a different set of attributes: - Sprite has `position` and `texcoord0`. - Tilegrid has `position` and `texcoord0`. - GUI node has `position`, `textcoord0` and `color`. - ParticleFX has `position`, `texcoord0` and `color`. - Model has `position`, `texcoord0` and `normal`. - Font has `position`, `texcoord0`, `face_color`, `outline_color` and `shadow_color`. Constants : Shader constants remain constant for the duration of the render draw call. Constants are added to the material file *Constants* sections and then declared as `uniform` in the shader program. Sampler uniforms are added to the *Samplers* section of the material and then declared as `uniform` in the shader program. The matrices necessary to perform vertex transformations in a vertex shader are available as constants: - `CONSTANT_TYPE_WORLD` is the *world matrix* that maps from an object’s local coordinate space into world space. - `CONSTANT_TYPE_VIEW` is the *view matrix* that maps from world space to camera space. - `CONSTANT_TYPE_PROJECTION` is the *projection matrix* that maps from camera to screen space. - Premultiplied $world * view$, $view * projection$ and $world * view$ matrices are also available. - `CONSTANT_TYPE_USER` is a `vec4` type constant that you can use as you wish. The [Material manual](#manuals:material) explains how to specify constants. Samplers : Shaders can declare *sampler* type uniform variables. Samplers are used to read values from an image source: - `sampler2D` samples from a 2D image texture. - `sampler2DArray` samples from a 2D image array texture. This is mostly used for paged atlases. - `samplerCube` samples from a 6 image cubemap texture. - `image2D` loads (and potentially stores) texture data to an image object. This is mostly used for compute shaders for storage. You can use a sampler only in the GLSL standard library's texture lookup functions. The [Material manual](#manuals:material) explains how to specify sampler settings. UV coordinates : A 2D coordinate is associated with a vertex and it maps to a point on a 2D texture. A portion, or the whole, of the texture can therefore be painted onto the shape described by a set of vertices. A UV-map is typically generated in the 3D modeling program and stored in the mesh. The texture coordinates for each vertex are provided to the vertex shader as an attribute. A varying variable is then used to find the UV coordinate for each fragment as interpolated from the vertex values. Varying variables : Varying types of variables are used to pass information between the vertex stage and the fragment stage. 1. A varying variable is set in the vertex shader for each vertex. 2. During rasterization this value is interpolated for each fragment on the primitive being rendered. The distance of the fragment to the shape's vertices dictates the interpolated value. 3. The variable is set for each call to the fragment shader and can be used for fragment calculations. For instance, setting a varying to a `vec3` RGB color value on each corners of a triangle will interpolate the colors across the whole shape. Similarly, setting texture map lookup coordinates (or *UV-coordinates*) on each vertex in a rectangle allows the fragment shader to look up texture color values for the whole area of the shape. ## Writing modern GLSL shaders Since the Defold engine supports multiple platforms and graphics APIs, it must be simple for developers to write shaders that works everywhere. The asset pipeline achieves this in mainly two ways (denoted as `shader pipelines` from now on): 1. The legacy pipeline, where shaders are written in ES2 compatible GLSL code. 2. The modern pipeline, where shaders are written in SPIR-v compatible GLSL code. Starting with Defold 1.9.2, it is encouraged to write shaders that utilize the new pipeline, and to achieve this most shaders need to be migrated into shaders written in at least version 140 (OpenGL 3.1). To migrate a shader, make sure these requirements are met: ### Version declaration Put at least #version 140 at the top of the shader: ```glsl #version 140 ``` This is how the shader pipeline is picked in the build process, which is why you can still use the old shaders. If no version preprocessor was found, Defold will fallback to the legacy pipeline. ### Attributes In vertex shaders, replace the `attribute` keyword with `in`: ```glsl // instead of: // attribute vec4 position; // do: in vec4 position; ``` Note: Fragment shaders (and compute shaders) does not take any vertex inputs. ### Varyings In vertex shaders, varyings should be prefixed with `out`. In fragment shaders, varyings becomes `in`: ```glsl // In a vertex shader, instead of: // varying vec4 var_color; // do: out vec4 var_color; // In a fragment shader, instead of: // varying vec4 var_color; // do: in vec4 var_color; ``` ### Uniforms (called constants in Defold) Opaque uniform types (samplers, images, atomics, SSBOs) does not need any migration, you can use them as you do today: ```glsl uniform sampler2D my_texture; uniform image2D my_image; ``` For non-opaque uniform types, you need to put them in a `uniform block`. A uniform block is simply a collection of uniform variables, and is declared with the `uniform` keyword: ```glsl uniform vertex_inputs { mat4 mtx_world; mat4 mtx_proj; mat4 mtx_view; mat4 mtx_normal; ... }; void main() { // Individual members of the uniform block can be used as-is gl_Position = mtx_proj * mtx_view * mtx_world * vec4(position, 1.0); } ``` All members in the uniform block is exposed to materials and components as individual constants. No migration is needed for using render constant buffers, or `go.set` and `go.get`. ### Built-in Variables In fragment shaders, `gl_FragColor` is deprecated starting with version 140. Use `out` instead: ```glsl // instead of: // gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // do: out vec4 color_out; void main() { color_out = vec4(1.0, 0.0, 0.0, 1.0); } ``` ### Texture functions Specific texture sampling functions such as `texture2D` and `texture2DArray` doesn't exist anymore. Instead, just use the `texture` function: ```glsl uniform sampler2D my_texture; uniform sampler2DArray my_texture_array; // instead of: // vec4 sampler_2d = texture2D(my_texture, uv); // vec4 sampler_2d_array = texture2DArray(my_texture_array, vec3(uv, slice)); // do: vec4 sampler_2d = texture(my_texture, uv); vec4 sampler_2d_array = texture(my_texture_array, vec3(uv, slice)); ``` ### Precision Setting explicit precision for variables, inputs, outputs and so forth was previously required in order to be compliant with OpenGL ES contexts. This is not required anymore, precision is now set automatically for platforms that support it. ### Putting it together As a final example where all of these rules are applied, here is the builtin sprite shaders converted into the new format: ```glsl #version 140 uniform vx_uniforms { mat4 view_proj; }; // positions are in world space in vec4 position; in vec2 texcoord0; out vec2 var_texcoord0; void main() { gl_Position = view_proj * vec4(position.xyz, 1.0); var_texcoord0 = texcoord0; } ``` ```glsl #version 140 in vec2 var_texcoord0; out vec4 color_out; uniform sampler2D texture_sampler; uniform fs_uniforms { vec4 tint; }; void main() { // Premultiply alpha since all runtime textures already are vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w); color_out = texture(texture_sampler, var_texcoord0.xy) * tint_pm; } ``` ## Including snippets into shaders Shaders in Defold support including source code from files within the project that have have the `.glsl` extension. To include a glsl file from a shader, use the `#include` pragma either with double quotations or brackets. Includes must have either project relative paths or a path that is relative from the file that is including it: ```glsl // In file /main/my-shader.fp // Absolute path #include "/main/my-snippet.glsl" // The file is in the same folder #include "my-snippet.glsl" // The file is in a sub-folder on the same level as 'my-shader' #include "sub-folder/my-snippet.glsl" // The file is in a sub-folder on the parent directory, i.e /some-other-folder/my-snippet.glsl #include "../some-other-folder/my-snippet.glsl" // The file is on the parent directory, i.e /root-level-snippet.glsl #include "../root-level-snippet.glsl" ``` There are some caveats to how includes are picked up: - Files must be project relative, meaning that you can only include files that are located within the project. Any absolute path must be specified with a leading `/` - You can include code anywhere in the file, but you cannot include a file inline in a statement. E.g `const float #include "my-float-name.glsl" = 1.0` will not work ### Header guards Snippets can themselves include other `.glsl` files, which means that the final produced shader can potentially include the same code several times, and depending on the contents of the files you can end up with compile issues due to having the same symbols stated more than once. To avoid this, you can use *header guards*, which is a common concept in several programming languages. Example: ```glsl // In my-shader.vs #include "math-functions.glsl" #include "pi.glsl" // In math-functions.glsl #include "pi.glsl" // In pi.glsl const float PI = 3.14159265359; ``` In this example, the `PI` constant will be defined twice, which will cause compiler errors when running the project. You should instead protect the contents with header guards: ```glsl // In pi.glsl #ifndef PI_GLSL_H #define PI_GLSL_H const float PI = 3.14159265359; #endif // PI_GLSL_H ``` The code from `pi.glsl` will be expanded twice in `my-shader.vs`, but since you have wrapped it in header guards the PI symbol will only be defined once and the shader will compile successfully. However, this is not always strict necessary depending of use-case. If instead you want to reuse code locally in a function or elsewhere where you don't need the values to be globally available in the shader code, you should probably not use header guards. Example: ```glsl // In red-color.glsl vec3 my_red_color = vec3(1.0, 0.0, 0.0); // In my-shader.fp vec3 get_red_color() { #include "red-color.glsl" return my_red_color; } vec3 get_red_color_inverted() { #include "red-color.glsl" return 1.0 - my_red_color; } ``` ## Editor-specific shader code When shaders are rendered in the Defold Editor viewport, a preprocessor definition `EDITOR` is available. This allows you to write shader code that behaves differently when running in the editor versus when running in the actual game engine. This is particularly useful for: - Adding debug visualizations that should only appear in the editor. - Implementing editor-specific features like wireframe modes or material previews. - Providing fallback rendering for materials that might not work properly in the editor viewport. Use the `#ifdef EDITOR` preprocessor directive to conditionally compile code that should only run in the editor: ```glsl #ifdef EDITOR // This code will only execute when the shader is rendered in the Defold Editor color_out = vec4(1.0, 0.0, 1.0, 1.0); // Magenta color for editor preview #else // This code will execute when running in the game color_out = texture(texture_sampler, var_texcoord0) * tint_pm; #endif ``` ## The rendering process Before ending up on the screen, the data that you create for your game goes through a series of steps: All visual components (sprites, GUI nodes, particle effects or models) consists of vertices, points in 3D world that describe the shape of the component. The good thing by this is that it is possible to view the shape from any angle and distance. The job of the vertex shader program is to take a single vertex and translate it into a position in the viewport so the shape can end up on screen. For a shape with 4 vertices, the vertex shader program runs 4 times, each in parallel. The input of the program is the vertex position (and other attribute data associated with the vertex) and the output is a new vertex position (`gl_Position`) as well as any `varying` variables that should be interpolated for each fragment. The most simple vertex shader program just sets the position of the output to a zero vertex (which is not very useful): ```glsl void main() { gl_Position = vec4(0.0,0.0,0.0,1.0); } ``` A more complete example is the built-in sprite vertex shader: ```glsl -- sprite.vp uniform mediump mat4 view_proj; // [1] attribute mediump vec4 position; // [2] attribute mediump vec2 texcoord0; varying mediump vec2 var_texcoord0; // [3] void main() { gl_Position = view_proj * vec4(position.xyz, 1.0); // [4] var_texcoord0 = texcoord0; // [5] } ``` 1. A uniform (constant) containing the view and projection matrices multiplied. 2. Attributes for the sprite vertex. `position` is already transformed into world space. `texcoord0` contains the UV coordinate for the vertex. 3. Declare a varying output variable. This variable will be interpolated for each fragment between the values set for each vertex and sent to the fragment shader. 4. `gl_Position` is set to the output position of the current vertex in projection space. This value has 4 components: `x`, `y`, `z` and `w`. The `w` component is used to calculate perspective-correct interpolation. This value is normally 1.0 for each vertex before any transformation matrix is applied. 5. Set the varying UV coordinate for this vertex position. After rasterization it will be interpolated for each fragment and sent to the fragment shader. After vertex shading, the on screen shape of the component is decided: primitive shapes are generated and rasterized, meaning that the graphics hardware splits each shape into *fragments*, or pixels. It then runs the fragment shader program, once for each of the fragments. For an on screen image 16x24 pixels in size, the program runs 384 times, each in parallel. The input of the program is whatever the rendering pipeline and the vertex shader sends, usually the *uv-coordinates* of the fragment, tint colors etc. The output is the final color of the pixel (`gl_FragColor`). The most simple fragment shader program just sets the color of each pixel to black (again, not a very useful program): ```glsl void main() { gl_FragColor = vec4(0.0,0.0,0.0,1.0); } ``` Again, a more complete example is the built-in sprite fragment shader: ```glsl // sprite.fp varying mediump vec2 var_texcoord0; // [1] uniform lowp sampler2D DIFFUSE_TEXTURE; // [2] uniform lowp vec4 tint; // [3] void main() { lowp vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w); // [4] lowp vec4 diff = texture2D(DIFFUSE_TEXTURE, var_texcoord0.xy);// [5] gl_FragColor = diff * tint_pm; // [6] } ``` 1. The varying texture coordinate variable is declared. The value of this variable will be interpolated for each fragment between the values set for each vertex in the shape. 2. A `sampler2D` uniform variable is declared. The sampler, together with the interpolated texture coordinates, is used to perform texture lookup so the sprite can be textured properly. Since this is a sprite, the engine will assign this sampler to the image set in the sprite's *Image* property. 3. A constant of type `CONSTANT_TYPE_USER` is defined in the material and declared as a `uniform`. Its value is used to allow color tinting of the sprite. The default is pure white. 4. The color value of the tint gets premultiplied with its alpha value since all runtime textures already contain premultiplied alpha. 5. Sample the texture at the interpolated coordinate and return the sampled value. 6. `gl_FragColor` is set to the output color for the fragment: the diffuse color from the texture multiplied with the tint value. The resulting fragment value then goes through tests. A common test is the *depth test* in where the fragment's depth value is compared against the depth buffer value for the pixel that is being tested. Depending on the test, the fragment can be discarded or a new value is written to the depth buffer. A common use of this test is to allow graphics that is closer to the camera to block graphics further back. If the test concluded that the fragment is to be written to the frame buffer, it will be *blended* with the pixel data already present in the buffer. Blending parameters that are set in the render script allow the source color (the value written by the fragment shader) and the destination color (the color from the image in the framebuffer) to be combined in various ways. A common use of blending is to enable rendering transparent objects. ## Further study - [Shadertoy](https://www.shadertoy.com) contains a massive number of user contributed shaders. It is a great source of inspiration where you can learn about various shading techniques. Many of the shaders showcased on the site can be ported to Defold with very little work. The [Shadertoy tutorial](https://www.defold.com/tutorials/shadertoy/) goes through the steps of converting an existing shader to Defold. - The [Grading tutorial](https://www.defold.com/tutorials/grading/) shows how to create a full screen color grading effect using color lookup table textures for the grading. - [The Book of Shaders](https://thebookofshaders.com/00/) will teach you how to use and integrate shaders into your projects, improving their performance and graphical quality. # Physically Based Rendering (PBR) {#manuals:physically-based-rendering} Physically Based Rendering (PBR) is a shading approach that models how light interacts with surfaces using real-world physical principles. It produces consistent, realistic lighting across different environments and allows assets to look correct under a wide range of lighting conditions. Defold’s PBR implementation follows the glTF 2.0 material specification and associated Khronos extensions. When you import glTF assets into Defold, material properties are automatically parsed and stored as structured material data that can be accessed in shaders at runtime. PBR materials can include effects such as metallic reflections, surface roughness, transmission, clearcoat, subsurface scattering, iridescence, and more. Defold currently exposes PBR material data to shaders, but does not provide a built-in PBR lighting model. You can use this data in your own lighting and reflection shaders to achieve physically based rendering. A default PBR lighting model will be added to Defold at a later stage. Embedded textures from glTF files are currently not automatically assigned in Defold. Only material parameters are exposed to shaders. You can still manually assign textures to model components and sample them in your shader. ## Material properties overview The material properties are parsed from the glTF 2.0 source files assigned to a model component. Not all properties are standard. Some are provided through optional glTF extensions that may or may not be included by the tool used to export the glTF file. The relevant extension is denoted in parentheses after the property name below. Metallic roughness : Describes how light interact with the material. The default PBR model. Specular glossiness (KHR_materials_pbrSpecularGlossiness) : An alternative to metallic roughness. Often used in older assets. Clearcoat (KHR_materials_clearcoat) : Adds a transparent coating layer with its own roughness and normal map. Ior (KHR_materials_ior) : Adds an index of refraction. Specular (KHR_materials_specular) : Adds a dedicated specular intensity and color channel. Iridescence (KHR_materials_iridescence) : Simulates thin-film interference for materials like soap bubbles or pearls. Sheen (KHR_materials_sheen) : Models fabric-like micro-surface reflections. Transmission (KHR_materials_transmission) : Models light transmission for transparent or glass-like materials. Volume (KHR_materials_volume) : Supports volumetric effects like thickness and attenuation. Emissive strength (KHR_materials_emissive_strength) : Controls emissive brightness independent of base color. Normal map : Normal map for surface detail. Occlusion map : Ambient occlusion map. Emissive map : Self-emissive texture for glowing surfaces. Emissive factor : RGB multiplier for emissive intensity Alpha cutoff : Threshold for masked transparency. Alpha mode : Opaque, Masked, or Blended transparency modes. Double sided : If true, both sides of the surface are rendered. Unlit : If true, the material bypasses lighting calculations. Some of these properties provides hints on how the material should be rendered. The data for the properties (alpha cutoff, alpha mode, double sided and unlit) is available in the shaders, but does not affect how the material is rendered in Defold. ## Shader integration The PBR material data is exposed to the shaders based on types and name convention. The PBR material system provides all parsed material parameters to shaders via a structured uniform block named `PbrMaterial`. Each supported glTF extension corresponds to a struct within this block, which can be conditionally compiled using #define flags. ```glsl uniform PbrMaterial { // Material properties }; ``` The various features of the material is specified as fixed structs in the shader. Data has been packed as much as possible in vec4's since that is how constants are set internally in Defold. In those cases where data has been packed, it is denoted as comments in the shader snippets for each feature below: ```glsl struct PbrMetallicRoughness { vec4 baseColorFactor; // R: metallic (Default=1.0), G: roughness (Default=1.0) vec4 metallicAndRoughnessFactor; // R: use baseColorTexture, G: use metallicRoughnessTexture vec4 metallicRoughnessTextures; }; struct PbrSpecularGlossiness { vec4 diffuseFactor; // RGB: specular (Default=1.0), A: glossiness (Default=1.0) vec4 specularAndSpecularGlossinessFactor; // R: use diffuseTexture, G: use specularGlossinessTexture vec4 specularGlossinessTextures; }; struct PbrClearCoat { // R: clearCoat (Default=0.0), G: clearCoatRoughness (Default=0.0) vec4 clearCoatAndClearCoatRoughnessFactor; // R: use clearCoatTexture, G: use clearCoatRoughnessTexture, B: use clearCoatNormalTexture vec4 clearCoatTextures; }; struct PbrTransmission { // R: transmission (Default=0.0) vec4 transmissionFactor; // R: use transmissionTexture vec4 transmissionTextures; }; struct PbrIor { // R: ior (Default=0.0) vec4 ior; }; struct PbrSpecular { // RGB: specularColor, A: specularFactor (Default=1.0); vec4 specularColorAndSpecularFactor; // R: use specularTexture, G: use specularColorTexture vec4 specularTextures; }; struct PbrVolume { // R: thicknessFactor (Default=0.0), RGB: attenuationColor vec4 thicknessFactorAndAttenuationColor; // R: attentuationDistance (Default=-1.0) vec4 attenuationDistance; // R: use thicknessTexture vec4 volumeTextures; }; struct PbrSheen { // RGB: sheenColor, A: sheenRoughnessFactor (Default=0.0) vec4 sheenColorAndRoughnessFactor; // R: use sheenColorTexture, G: use sheenRoughnessTexture vec4 sheenTextures; }; struct PbrEmissiveStrength { // R: emissiveStrength (Default=1.0) vec4 emissiveStrength; }; struct PbrIridescence { // R: iridescenceFactor (Default=0.0), G: iridescenceIor (Default=1.3), B: iridescenceThicknessMin (Default=100.0), A: iridescenceThicknessMax (Default=400.0) vec4 iridescenceFactorAndIorAndThicknessMinMax; // R: use iridescenceTexture, G: use iridescenceThicknessTexture vec4 iridescenceTextures; }; ``` The common properties are set on the material uniform itself (and once again, note the data packing into vec4). ```glsl // Common textures uniform sampler2D PbrMaterial_normalTexture; uniform sampler2D PbrMaterial_occlusionTexture; uniform sampler2D PbrMaterial_emissiveTexture; uniform PbrMaterial { // Common properties: // R: alphaCutoff (Default=0.5), G: doubleSided (Default=false), B: unlit (Default=false) vec4 pbrAlphaCutoffAndDoubleSidedAndIsUnlit; // R: use normalTexture, G: use occlusionTexture, B: use emissiveTexture vec4 pbrCommonTextures; // Other properties... }; ``` ### Example shader Here is an example shader that contains all features and a proposed naming scheme for texture bindings (again, this must be handled manually). Note that you can turn off features simply by using defines around each member of the PbrMaterial itself, as shown in the example below: ```glsl // Feature flags, comment or remove these to slim down the shader. #define PBR_METALLIC_ROUGHNESS #define PBR_SPECULAR_GLOSSINESS #define PBR_CLEARCOAT #define PBR_TRANSMISSION #define PBR_IOR #define PBR_SPECULAR #define PBR_VOLUME #define PBR_SHEEN #define PBR_EMISSIVE_STRENGTH #define PBR_IRIDESCENCE // Common uniform sampler2D PbrMaterial_normalTexture; uniform sampler2D PbrMaterial_occlusionTexture; uniform sampler2D PbrMaterial_emissiveTexture; // PbrMetallicRoughness uniform sampler2D PbrMetallicRoughness_baseColorTexture; uniform sampler2D PbrMetallicRoughness_metallicRoughnessTexture; struct PbrMetallicRoughness { vec4 baseColorFactor; // R: metallic (Default=1.0), G: roughness (Default=1.0) vec4 metallicAndRoughnessFactor; // R: use baseColorTexture, G: use metallicRoughnessTexture vec4 metallicRoughnessTextures; }; // PbrSpecularGlossiness uniform sampler2D PbrSpecularGlossiness_diffuseTexture; uniform sampler2D PbrSpecularGlossiness_specularGlossinessTexture; struct PbrSpecularGlossiness { vec4 diffuseFactor; // RGB: specular (Default=1.0), A: glossiness (Default=1.0) vec4 specularAndSpecularGlossinessFactor; // R: use diffuseTexture, G: use specularGlossinessTexture vec4 specularGlossinessTextures; }; // PbrClearCoat uniform sampler2D PbrClearCoat_clearcoatTexture; uniform sampler2D PbrClearCoat_clearcoatRoughnessTexture; uniform sampler2D PbrClearCoat_clearcoatNormalTexture; struct PbrClearCoat { // R: clearCoat (Default=0.0), G: clearCoatRoughness (Default=0.0) vec4 clearCoatAndClearCoatRoughnessFactor; // R: use clearCoatTexture, G: use clearCoatRoughnessTexture, B: use clearCoatNormalTexture vec4 clearCoatTextures; }; // PbrTransmission uniform sampler2D PbrTransmission_transmissionTexture; struct PbrTransmission { // R: transmission (Default=0.0) vec4 transmissionFactor; // R: use transmissionTexture vec4 transmissionTextures; }; struct PbrIor { // R: ior (Default=0.0) vec4 ior; }; // PbrSpecular uniform sampler2D PbrSpecular_specularTexture; uniform sampler2D PbrSpecular_specularColorTexture; struct PbrSpecular { // RGB: specularColor, A: specularFactor (Default=1.0); vec4 specularColorAndSpecularFactor; // R: use specularTexture, G: use specularColorTexture vec4 specularTextures; }; // PbrVolume uniform sampler2D PbrVolume_thicknessTexture; struct PbrVolume { // R: thicknessFactor (Default=0.0), RGB: attenuationColor vec4 thicknessFactorAndAttenuationColor; // R: attentuationDistance (Default=-1.0) vec4 attenuationDistance; // R: use thicknessTexture vec4 volumeTextures; }; // PbrSheen uniform sampler2D PbrSheen_sheenColorTexture; uniform sampler2D PbrSheen_sheenRoughnessTexture; struct PbrSheen { // RGB: sheenColor, A: sheenRoughnessFactor (Default=0.0) vec4 sheenColorAndRoughnessFactor; // R: use sheenColorTexture, G: use sheenRoughnessTexture vec4 sheenTextures; }; struct PbrEmissiveStrength { // R: emissiveStrength (Default=1.0) vec4 emissiveStrength; }; // PbrIridescence uniform sampler2D PbrEmissive_iridescenceTexture; uniform sampler2D PbrEmissive_iridescenceThicknessTexture; struct PbrIridescence { // R: iridescenceFactor (Default=0.0), G: iridescenceIor (Default=1.3), B: iridescenceThicknessMin (Default=100.0), A: iridescenceThicknessMax (Default=400.0) vec4 iridescenceFactorAndIorAndThicknessMinMax; // R: use iridescenceTexture, G: use iridescenceThicknessTexture vec4 iridescenceTextures; }; uniform PbrMaterial { // Common properties // R: alphaCutoff (Default=0.5), G: doubleSided (Default=false), B: unlit (Default=false) vec4 pbrAlphaCutoffAndDoubleSidedAndIsUnlit; // R: use normalTexture, G: use occlusionTexture, B: use emissiveTexture vec4 pbrCommonTextures; // Features #ifdef PBR_METALLIC_ROUGHNESS PbrMetallicRoughness pbrMetallicRoughness; #endif #ifdef PBR_SPECULAR_GLOSSINESS PbrSpecularGlossiness pbrSpecularGlossiness; #endif #ifdef PBR_CLEARCOAT PbrClearCoat pbrClearCoat; #endif #ifdef PBR_TRANSMISSION PbrTransmission pbrTransmission; #endif #ifdef PBR_IOR PbrIor pbrIor; #endif #ifdef PBR_SPECULAR PbrSpecular pbrSpecular; #endif #ifdef PBR_VOLUME PbrVolume pbrVolume; #endif #ifdef PBR_SHEEN PbrSheen pbrSheen; #endif #ifdef PBR_EMISSIVE_STRENGTH PbrEmissiveStrength pbrEmissiveStrength; #endif #ifdef PBR_IRIDESCENCE PbrIridescence pbrIridescence; #endif }; ``` If specific data points in the material struct are not found, the data for those features will not be set. E.g if there is no `pbrClearCoat` in the material struct, no clear coat data will be set. If the uniform block is not found, no data at all will be set during rendering. ### Constants Each material property corresponds to an internal render constant in Defold. You can override default values by defining constants on the material resource itself, following the naming pattern `pbrFeature.structMember`. These values will be applied automatically if the matching data is missing in the glTF material. ## Next steps To use the material data for physically based lighting, implement a BRDF in your fragment shader using the parameters provided in the `PbrMaterial` block. See also: * [Shaders manual](#manuals:shader) * [Render manual](#manuals:render) * [glTF 2.0 specification](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html) # Bundling an application {#manuals:bundling} While developing your application you should make a habit of testing the game on the target platforms as often as possible. You should do this to detect performance issues early on in the development process where these things are much easier to fix. It is also recommended to test on all target platforms to find discrepancies in things such as shaders. When developing on mobile you have the option to use the [mobile development app](#manuals:dev-app) to push content to the app, instead of having to do a full bundle and uninstall/install cycle. You can create an application bundle for all platforms that Defold supports from within the Defold editor itself, with no external tools needed. You can also bundle from the command line using our command line tools. Application bundling requires a network connection if your project contains one or more [native extensions](#manuals:extensions). ## Bundling from within the editor You create an application bundle from the Project menu and Bundle option: Selecting any of the menu options will bring up the Bundle dialog for that specific platform. ### 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. To learn more about build reports please refer to the [Profiling manual](#manuals:profiling). ### Android Creating an Android application bundle (.apk file) is documented in the [Android manual](#manuals:android). ### iOS Creating an iOS application bundle (.ipa file) is documented in the [iOS manual](#manuals:ios). ### macOS Creating a macOS application bundle (.app file) is documented in the [macOS manual](#manuals:macos). ### Linux Creating a Linux application bundle requires no specific setup and no optional platform specific configuration in the *game.project* [project settings file](#manuals:project-settings). ### Windows Creating a Windows application bundle (.exe file) is documented in the [Windows manual](#manuals:windows). ### HTML5 Creating an HTML5 application bundle as well as optional setup is documented in the [HTML5 manual](#manuals:html5). #### Facebook Instant Games It is possible to create a special version of an HTML5 application bundle specifically for Facebook Instant Games. This process is documented in the [Facebook Instant Games manual](#manuals:instant-games). ## Bundling from the command line The editor uses our command line tool [Bob](#manuals:bob) to bundle the application. While doing day to day development of your application it is likely that you build and bundle from within the Defold editor. In other circumstances you may wish to automatically generate application bundles, for instance batch building for all targets when releasing a new version or when creating nightly builds of the latest version of the game, perhaps in a CI environment. Building and bundling of an application can be done outside the normal editor workflow using the [Bob command line tool](#manuals:bob). ## The bundle layout The logical bundle layout is structured like this: A bundle is output into a folder. Depending on platform, that folder may also be zip archived into an `.apk` or `.ipa`. The contents of the folder depends on the platform. Apart from the executable files, our bundling process also collects the required assets for the platform (e.g. the .xml resource files for Android). Using the [bundle_resources](#manuals:project-settings) setting, you can configure assets that should be placed within the bundle as-is. You can control this per platform. The game assets are located in the `game.arcd` file, and they are individually compressed using LZ4 compression. Using the [custom_resources](#manuals:project-settings) setting, you can configure assets that should be placed (with compression) within the `game.arcd`. These assets can be accessed via the [`sys.load_resource()`](https://defold.com/ref/sys/#sys.load_resource) function. ## Release vs Debug When creating an application bundle you have an option of creating a debug or release bundle. The differences between the two bundles are small but important to keep in mind: * Release builds do not include the [profiler](#manuals:profiling) * Release builds do not include the [screen recorder](https://defold.com/ref/stable/sys/#start_record) * Release builds do not show the output of any calls to `print()` or the output from any native extensions * Release builds have the `is_debug` value in `sys.get_engine_info()` set to`false` * Release builds will not do reverse lookups of `hash` values when calling `tostring()`. What this means in practice is that a `tostring()` for a value of type `url` or `hash` will return its numeric representation and not the original string (`'hash: [/camera_001]'` vs `'hash: [11844936738040519888 (unknown)]'`) * Release builds do not support targeting from the editor for [hot-reload](#manuals:hot-reload) and similar functionality # Bob the builder {#manuals:bob} Bob is a command line tool for building Defold projects outside of the normal editor workflow. Bob is able to build data (corresponding to the build step of selecting the editor menu item `Project ▸ Build`), create data archives and create standalone, distributable application bundles (corresponding to the editor menu item `Project ▸ Bundle ▸ ...` options) Bob is distributed as a Java _JAR_ archive containing everything needed to build. You find the latest *bob.jar* distribution on the [GitHub Releases page](https://github.com/defold/defold/releases). Select a release, then download *bob/bob.jar*. If you are using Defold 1.12.0 or newer, you will need OpenJDK 25 to run it. For older versions of Defold, you will need openJDK 21. Compatible OpenJDK 25 mirrors (from Defold 1.12.0): * [OpenJDK 25 by Microsoft](https://learn.microsoft.com/en-us/java/openjdk/download#openjdk-25) * [OpenJDK 25 by Adoptium Working Group](https://github.com/adoptium/temurin25-binaries/releases) / [Adoptium.net](https://adoptium.net/) If you are on Windows you want the `.msi` file installer for OpenJDK. Legacy Live Update manifest-signing flags `--manifest-private-key` and `--manifest-public-key` have been removed from Bob. The `publickey` and `privatekey` entries in `liveupdate.settings` are now deprecated and unused, `game.public.der` is no longer generated or bundled, and the deprecated manifest/archive validation flow now checks supported engine versions instead of bundled key signatures. ## Usage Bob is run from a shell or from the command line by invoking `java` (or `java.exe` on Windows) and providing the bob java archive as argument: ```text $ java -jar bob.jar --help usage: bob [options] [commands] -a,--archive Build archive -ar,--architectures Comma separated list of architectures to include for the platform --archive-resource-padding The alignment of the resources in the game archive. Default is 4 -bf,--bundle-format Which formats to create the application bundle in. Comma separated list. (Android: 'apk' and 'aab') --binary-output Location where built engine binary will be placed. Default is "//" -bo,--bundle-output Bundle output directory -br,--build-report DEPRECATED! Use --build-report-json instead -brhtml,--build-report-html Filepath where to save a build report as HTML -brjson,--build-report-json Filepath where to save a build report as JSON --build-artifacts If left out, will default to build the engine. Choices: 'engine', 'plugins', 'library'. Comma separated list. --build-server The build server (when using native extensions) --build-server-header Additional build server header to set -ce,--certificate DEPRECATED! Use --keystore instead -d,--debug DEPRECATED! Use --variant=debug instead --debug-ne-upload Outputs the files sent to build server as upload.zip --debug-output-spirv Force build SPIR-V shaders --debug-output-wgsl Force build WGSL shaders --defoldsdk What version of the defold sdk (sha1) to use -e,--email User email -ea,--exclude-archive Exclude resource archives from application bundle. Use this to create an empty Defold application for use as a build target --exclude-build-folder DEPRECATED! Use '.defignore' file instead -h,--help This help message -i,--input DEPRECATED! Use --root instead --identity Sign identity (iOS) -kp,--key-pass Password of the deployment key if different from the keystore password (Android) -ks,--keystore Deployment keystore used to sign APKs (Android) -ksa,--keystore-alias The alias of the signing key+cert you want to use (Android) -ksp,--keystore-pass Password of the deployment keystore (Android) -l,--liveupdate Yes if liveupdate content should be published --max-cpu-threads Max count of threads that bob.jar can use -mp,--mobileprovisioning mobileprovisioning profile (iOS) --ne-build-dir Specify a folder with includes or source, to build a specific library. More than one occurrence is allowed. --ne-output-name Specify a library target name -o,--output Output directory. Default is "build/default" -p,--platform Platform (when building and bundling) -pk,--private-key DEPRECATED! Use --keystore instead -r,--root Build root directory. Default is current directory --resource-cache-local Path to local resource cache. --resource-cache-remote URL to remote resource cache. --resource-cache-remote-pass Password/token to authenticate access to the remote resource cache. --resource-cache-remote-user Username to authenticate access to the remote resource cache. --settings Path to a game project settings file. More than one occurrence is allowed. The settings files are applied left to right. --strip-executable Strip the dmengine of debug symbols (when bundling iOS or Android) -tc,--texture-compression Use texture compression as specified in texture profiles -tp,--texture-profiles DEPRECATED! Use --texture-compression instead -u,--auth User auth token --use-async-build-server DEPRECATED! Asynchronous build is now the default. --use-lua-bytecode-delta Use byte code delta compression when building for multiple architectures --use-uncompressed-lua-source Use uncompressed and unencrypted Lua source code instead of byte code --use-vanilla-lua DEPRECATED! Use --use-uncompressed-lua-source instead. -v,--verbose Verbose output --variant Specify debug, release or headless version of dmengine (when bundling) --version Prints the version number to the output --with-symbols Generate the symbol file (if applicable) ``` Available commands: `clean` : Delete built files in the build directory. `distclean` : Delete all files in the build directory. `build` : Builds all project data. Add the `--archive` option to build a data archive file ("`game.darc`" in the build directory). `bundle` : Creates a platform specific application bundle. Bundling requires that a built archive is present (`build` with the `--archive` option) and that a target platform is specified (with the `--platform` option). Bob creates the bundle in the output directory unless a different directory is specified with the `--bundle-output` option. The bundle is named according to the project name setting in *game.project*. The `--variant` specifies which type of executable to build when bundling and it together with the `--strip-executable` option replaces the `--debug` option. If no `--variant` is specified you will get a release version of the engine (stripped of symbols on Android and iOS). Setting `--variant` to debug and omitting `--strip-executable` yields the same type of executable as `--debug` used to do. `resolve` : Resolve all external library dependencies. Available platforms and architectures: `x86_64-darwin` (Defold 1.3.5 and older) `x86_64-macos` (Defold 1.3.6 and newer) : macOS 64 bit `arm64-macos` (Defold 1.5.0 and older) : macOS Apple Silicon (ARM) `x86_64-win32` : Windows 64 bit `x86-win32` : Windows 32 bit `x86_64-linux` : Linux 64 bit `x86_64-ios` : iOS macOS 64 bit (iOS Simulator) `armv7-darwin` (Defold 1.3.5 and older) `armv7-ios` (Defold 1.3.6 and newer) : iOS with available 32-bit `armv7-darwin` and 64-bit `arm64-darwin` architectures. By default, `--architectures` argument value is `armv7-darwin,arm64-darwin`. `armv7-android` : Android with available 32 bit `armv7-android` and 64 bit `arm64-android` architectures. By default, `--architectures` argument value is `armv7-android,arm64-android`. `js-web` : HTML5 with available `js-web`, `wasm-web` and `wasm_pthread-web` architectures. By default, `--architectures` argument value is `js-web,wasm-web`. By default, Bob looks in the current directory for a project to build. If you change the current dir to a Defold project and invoke bob, it builds the data for the project in the default output directory *build/default*. ```sh $ cd /Applications/Defold-beta/branches/14/4/main $ java -jar bob.jar 100% $ ``` You can string commands together to perform a sequence of tasks in one go. The following example resolves libraries, wipes the build directory, builds archive data and bundles a macOS application (named *My Game.app*): ```sh $ java -jar bob.jar --archive --platform x86-darwin resolve distclean build bundle 100% $ ls -al build/default/ total 70784 drwxr-xr-x 13 sicher staff 442 1 Dec 10:15 . drwxr-xr-x 3 sicher staff 102 1 Dec 10:15 .. drwxr-xr-x 3 sicher staff 102 1 Dec 10:15 My Game.app drwxr-xr-x 8 sicher staff 272 1 Dec 10:15 builtins -rw-r--r-- 1 sicher staff 140459 1 Dec 10:15 digest_cache drwxr-xr-x 4 sicher staff 136 1 Dec 10:15 fonts -rw-r--r-- 1 sicher staff 35956340 1 Dec 10:15 game.darc -rw-r--r-- 1 sicher staff 735 1 Dec 10:15 game.projectc drwxr-xr-x 223 sicher staff 7582 1 Dec 10:15 graphics drwxr-xr-x 3 sicher staff 102 1 Dec 10:15 input drwxr-xr-x 20 sicher staff 680 1 Dec 10:15 logic drwxr-xr-x 27 sicher staff 918 1 Dec 10:15 sound -rw-r--r-- 1 sicher staff 131926 1 Dec 10:15 state $ ``` # Hot reloading resources {#manuals:hot-reload} 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 (`Project ▸ Build`). To then reload an updated resource simply select the menu item `File ▸ Hot Reload` or press the corresponding shortcut on the keyboard: ## Hot reloading on device Hot reloading works 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: 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: Add the new buttons, save and hot reload the GUI file. You can now see the new buttons on the phone screen: 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. # Porting and release guidelines {#manuals:porting-guidelines} This page contains a helpful guide and checklist of things to consider when releasing a game or when porting to a new platform. Porting a Defold game to a new platform or releasing for the first time is usually a straight forward process. In theory it is enough to make sure that the relevant sections are configured in the *game.project* file, but to make the most out of each platform it is recommended to adapt the game to the specifics of each platform. ## Input Make sure to adapt the game to the input methods of the platform. Consider adding support for [gamepads](#manuals:input-gamepads) if the platform supports it! And make sure the game supports a pause menu - if a controller suddenly disconnects, the game should be paused! ## Localization Translate any text in the game. For release in Europe and Americas consider translating to at least EFIGS (English, French, Italian, German and Spanish). Make sure it is possible to easily swap between different languages in-game (via the pause menu). iOS only - Make sure you specify [Localizations](#manuals:project-settings) in `game.project`, since `sys.get_info()` will never return language which isn’t in this list. Translate the text on the store page as this will have a positive impact on sales! Some platforms require the text on the store page to be translated to the language of each country where the game is available. ## Store materials ### App icon Make sure your game stands out from the competition. The icon is often your first point of contact with potential players. It should be easy to find on a page full of game icons. ### Store banners and images Make sure to use impactful and exciting art for your game. It is probably worth spending some money to work with an artist to create art that attracts players. ## Save games ### Save games on desktop, mobile and web Save games and other saved state can be stored using Defold API function `sys.save(filename, data)` and loaded using `sys.load(filename)`. You can use `sys.get_save_file(application_id, name)` to get a path to an operating system specific location where files can be saved, typically in the logged in users home folder. ### Save games on console Using `sys.get_save_file()` and `sys.save()` works well on most platforms, but on consoles it is recommended to take a different approach. Console platforms typically associate a user with each connected controller, and as such save games, achievements and other features should be associated with their respective user. The gamepad input events will contain a user id which can be used to associate the actions of a controller with a user on the console. The console platforms and their native extensions will expose platform specific API functions to save and load data associated with a specific user. Use these APIs when saving and loading on console. Console platform APIs for file operations are typically asynchronous. When developing a cross platform game targeted for console it is recommended to design your game such that all file operations are asynchronous, regardless of platform. Example: ```lua local function save_game(data, user_id, cb) if console then local filename = "savegame" consoleapi.save(user_id, filename, data, cb) else local filename = sys.get_save_file("mygame", "savegame" .. user_id) local success = sys.save(filename, data) cb(success) end end ``` ## Build artifacts Make sure to [generate debug symbols](#manuals:debugging-native-code) for each released version so that you can debug crashes. Store these together with the application bundle. Make sure to store the `manifest.private.der` and `manifest.public.der` files which are generated in the project root during the first bundle. These are the public and private signing keys for the game archive and archive manifest. You need these files in order to recreate a previous build of your game. ## Application optimizations Read the [Optimization manual](#manuals:optimization) on how to optimize your application for performance, size, memory and battery usage. ## Performance Always test on target hardware! Check game performance and optimize if needed. Use the [profiler](#manuals:profiling) to find bottlenecks in the code. ## Screen resolution and refresh rate For platforms with a fixed orientation and screen resolution: Check that the game works on the target platform screen resolution and aspect ratio. For platforms with variable screen resolution and aspect ratio: Check that the game works on a variety of screen resolutions and aspect ratios. Take into consideration what kind of [view projection](#manuals:render) that is used in the render script and camera. For mobile platforms either lock the screen orientation in *game.project* or make sure the game works in both landscape and portrait mode. * **Display sizes** - Is everything looking good on a larger or smaller screen than the default width and height set in *game.project*? * The projection used in the render script and the layouts used in the gui will play a role here. * **Aspect ratios** - Is everything looking good on a screen with a different aspect ratio than the default aspect ratio from the width and height set in *game.project*? * The projection used in the render script and the layouts used in the gui will play a role here. * **Refresh rate** - Is the game running well on a screen with a higher refresh rate than 60 Hz? * The vsync and swap interval in the Display section of *game.project* ## Mobile phones and notch and hole punch cameras It has become increasingly popular to use a small lens cut-out on the display screen to fit in the front camera and sensors (also known as a notch or hole punch camera). When porting a game to mobile it is recommended to make sure that no critical information is positioned where a notch (center of upper screen edge) or hole-punch (top left screen area) is typically found. It is also possible to use the [Safe Area extension](/extension-safearea) to restrict the game view to the area outside any notch or hole-punch camera. ## Platform specific guidelines ### Android Make sure to store your [keystore](#manuals:android) somewhere safe so that you can update your game. ### Consoles Store the complete bundle for each version. You will need these files if you want to patch the game. ### Nintendo Switch Integrate platform specific code - For Nintendo Switch there's a separate extension with some helper functionality for user selection etc. Defold for Nintendo Switch uses Vulkan as the graphics backend - Make sure to test the game using the [Vulkan graphics backend](https://github.com/defold/extension-vulkan). ### PlayStation®4 Integrate platform specific code - For PlayStation®4 there's a separate extension with some helper functionality for user selection etc. ### HTML5 Playing web games on mobile phones is increasing in popularity - Try to make the game run well in a mobile browser as well! It is also important to keep in mind that web games are expected to load fast! - Make sure to optimize the game for size. Also consider the loading experience in general to not lose players unnecessarily. In 2018 browsers introduced an autoplay policy for sounds which prevent games and other web content from playing sounds until a user interaction event (touch, button, gamepad etc) has taken place. It is important to take this into account when porting to HTML5 and only start playing sounds and music upon first user interaction. Attempts to play sounds before any user interaction will be logged as an error in the browser developer console but will not impact the game. Also make sure to pause any playing sounds if the game is showing ads. # The mobile development app {#manuals:dev-app} The development app allows you to push content to it over wifi. This will greatly reduce iteration time as you don't have to bundle and install every time you wish to test your changes. You install the development app on your device(s), start the app and then select the device as a build target from the editor. ## Installing a development app Any iOS or Android application that is bundled in Debug mode will be able to act as a development app. In fact, this is the recommended solution as the development app will have the correct project settings and uses the same [native extensions](#manuals:extensions) as the project you are working on. Starting with Defold 1.4.0 it is possible to bundle a Debug variant of your project without any content. Use this option to create a version of your application with native extensions, suitable for iterative development as described in this manual. ### Installing on iOS Follow the [instructions in the iOS manual](#manuals:ios) to bundle for iOS. Make sure to select Debug as variant! ### Installing on Android Follow the [instructions in the Android manual](#manuals:android) to bundle for Android. ## Launching your game To launch your game on your device, the development app and editor must be able to connect, over the same wifi network or using USB (see below). 1. Make sure the editor is up and running. 2. Launch the development app on the device. 3. Select your device under `Project ▸ Targets` in the editor. 4. Select `Project ▸ Build` to run the game. It may take a while for the game to start since the game content is streamed to the device over the network. 5. While the game is running, you can use [hot reloading](#manuals:hot-reload) as usual. ### Connecting to an iOS device using USB on Windows When connecting over USB on Windows to a development app running on an iOS device you first need to [install iTunes](https://www.apple.com/lae/itunes/download/). When iTunes is installed you also need to [enable Personal Hotspot](https://support.apple.com/en-us/HT204023) on your iOS device from the Settings menu. If you see an alert that says tap "Trust This Computer?" tap Trust. The device should now show up under `Project ▸ Targets` when the development app is running. ### Connecting to an iOS device using USB on Linux On Linux you need to enable Personal Hotspot on your device from the Settings menu when connected using USB. If you see an alert that says tap "Trust This Computer?" tap Trust. The device should now show up under `Project ▸ Targets` when the development app is running. ### Connecting to an iOS device using USB on macOS On newer iOS versions the device will automatically open a new ethernet interface between the device and computer when connected using USB on macOS. The device should show up under `Project ▸ Targets` when the development app is running. On older iOS versions you need to enable Personal Hotspot on your device from the Settings menu when connected using USB on macOS. If you see an alert that says tap "Trust This Computer?" tap Trust. The device should now show up under `Project ▸ Targets` when the development app is running. ### Connecting to an Android device using USB on macOS On macOS it is possible to connect over USB to a running development app on an Android device when the device is in USB Tethering Mode. On macOS you need to install a third-party driver such as [HoRNDIS](https://joshuawise.com/horndis#available_versions). When HoRNDIS is installed you also need to allow it to run via the Security & Privacy settings. Once USB Tethering is enabled the device will show up under `Project ▸ Targets` when the development app is running. ### Connecting to an Android device using USB on Windows or Linux On Windows and Linux it is possible to connect over USB to a running development app on an Android device when the device is in USB Tethering Mode. Once USB Tethering is enabled the device will show up under `Project ▸ Targets` when the development app is running. ## Troubleshooting Unable to download application : Make sure the your device UDID is included in the mobile provisioning that was used for signing the app. Your device does not appear in the Targets menu : Make sure that your device is connected to the same wifi network as your computer. Make sure the development app is built in Debug mode. The game does not start with a message about mismatching versions : This happens when you have upgraded the editor to the latest version. You need to build and install a new version. # Version control {#manuals:version-control} Defold is built intended for small teams that work in intense collaboration to create games. Team members can work in parallel on the same content with very little friction. Defold has built-in support for version control using [Git](https://git-scm.com). Git is designed for distributed collaborative work and it is an extremely powerful tool that allows for a wide range of workflows. ## Changed files When you save changes in your local working copy, Defold tracks all changes in the *Changed Files* editor pane, listing each file that has either been added, deleted or modified. Select a file in the list and click `Diff` to view the changes that you have done to the file or `Revert` to undo all changes and restore the file to the state it had after the last synchronization. ## Git Git is built primarily to handle source code and text files and stores those types of files with a very low footprint. Only the changes between each version are stored, which means that you can keep an extensive history of changes to all your project files to a relatively small cost. Binary files such as image or sound files, however, does not benefit from Git's storage scheme. Each new version you check in and synchronize takes about the same space. That is usually not a major issue with final project assets (JPEG or PNG images, OGG sound files etc) but it can quickly become an issue with working project files (PSD files, Protools projects etc). These types of files often grow very large since you usually work in much higher resolution than the target assets. It is generally considered best to avoid putting large working files under the control of Git and instead use a separate storage and backup solution for those. There are many ways you can use Git in a team workflow. The one Defold uses is as follows. When you synchronize, the following happens: 1. Any local changes are stashed so they can be restored if something fails later in the sync process. 2. Server changes are pulled. 3. The stash is applied (the local changes are restored), this may result in merge conflicts that need to be resolved. 4. The user gets the option to commit any local file changes. 5. If there are local commits, the user may choose to push these to the server. Again, it is possible that this leads to conflicts that need to be resolved. If you prefer a different workflow you can run Git from command line or through a third party application to perform pulls, pushes, commits and merges, working on several branches and so on. # Working offline {#manuals:working-offline} Defold does in most cases not require an internet connection to work. There is however a few situations when an internet connection is needed: * Automatic updates * Reporting issues * Fetching dependencies * Building native extensions ## Automatic updates Defold will check periodically if new updates exist. Defold update checks are made to the [official download site](https://d.defold.com). If an update is detected it will automatically be downloaded. If you only have an internet connection for limited periods of time and don't wish to wait for the automatic update to trigger you can manually download new versions of Defold from the [official download site](https://d.defold.com). ## Reporting issues If a problem is detected in the editor you get a choice to report the issue to the Defold issue tracker. The issue tracker is [hosted on GitHub](https://www.github.com/defold/editor2-issues) which means you need an internet connection to report the issue. If you encounter an issue while offline you can manually report it later using the [Report Issue option in the Help menu](#manuals:getting-help) of the editor. ## Fetching dependencies Defold supports a system where developers can share code and assets through something called [Library Projects](#manuals:libraries). Libraries are zip files that can be hosted anywhere online. You typically find Defold library projects on GitHub and other online source code repositories. A project can add a library as a [project dependency in the project settings](#manuals:project-settings). Dependencies are downloaded/updated when the project is opened or any time when the *Fetch Libraries* option is selected from the *Project* menu. If you need to work offline and in multiple projects you can download dependencies in advance and then share them using a local server. Dependencies on GitHub are usually available from the Releases tab of the project repository: You can use Python to easily create a local server: python -m SimpleHTTPServer This will create a server in the current directory serving files on `localhost:8000`. If the current directory contains downloaded dependencies you can add these to your *game.project* file: http://localhost:8000/extension-fbinstant-4.1.1.zip ## Building native extensions Defold supports a system where developers can add native code to extend the functionality of the engine through a system called [Native Extensions](#manuals:extensions). Defold provides a zero setup entry point to native extensions with a cloud based build solution. The first time you build a project and the project contains a native extension the native code will get compiled into a custom Defold game engine on the Defold build servers and sent back to your PC. The custom engine will be cached in your project and reused for subsequent builds as long as you do not add, remove or change any native extensions and as long as you do not update the editor. If you need to work offline and your project contains native extensions you must make sure to build successfully at least once to ensure that your project contains a cached copy of the custom engine. # Debugging native code {#manuals:debugging-native-code} Defold is well tested and should very rarely crash under normal circumstances. It is however impossible to guarantee that it will never crash, especially if your game uses native extensions. If you run into problems with crashes or native code that doesn't behave as expected there are a number of different ways forward: * Use a debugger to step through the code * Use print debugging * Analyze a crash log * Symbolicate a callstack ## Use a debugger The most common way is to run the code via a `debugger`. It let's you step through the code, set `breakpoints` and it will stop the execution if you get a crash. There are several debuggers for each platform. * Visual studio - Windows * VSCode - Windows, macOS, Linux * Android Studio - Windows, macOS, Linux * Xcode - macOS * WinDBG - Windows * lldb / gdb - macOS, Linux, (Windows) * ios-deploy - macOS Each tool can debug certain platforms: * Visual studio - Windows + platforms supporting gdbserver (E.g. Linux/Android) * VSCode - Windows, macOS (lldb), Linux (lldb/gdb) + platforms supporting gdbserver * Xcode - macOS, iOS ([learn more](#manuals:debugging-native-code-ios)) * Android Studio - Android ([learn more](#manuals:debugging-native-code-android)) * WinDBG - Windows * lldb/gdb - macOS, Linux, (iOS) * ios-deploy - iOS (via lldb) ## Use print debugging The simplest way to debug your native code is to use [print debugging](http://en.wikipedia.org/wiki/Debugging#Techniques). Use the functions in the [`dmLog` namespace](https://defold.com/ref/stable/dmLog/) to watch variables or indicate the flow of execution. Using any of the log functions will print to the *Console* view in the editor and to the [game log](#manuals:debugging-game-and-system-logs). ## Analyze a crash log The Defold engine saves a `_crash` file if it does a hard crash. The crash file will contain information about the system as well as the crash. The [game log output](#manuals:debugging-game-and-system-logs) will write where the crash file is located (it varies depending on operating system, device and application). You can use the [crash module](https://www.defold.com/ref/crash/) to read this file in the subsequent session. It is recommended that you read the file, gather the information, print it to the console and send it to an [analytics services](https://defold.com/tags/stars/analytics/) that supports collection of crash logs. On Windows a `_crash.dmp` file is also generated. This file is useful when debugging a crash. ### Getting the crash log from a device If a crash happens on a mobile device you can chose to download the crash file to your own computer and parse it locally. #### Android If the app is [debuggable](#manuals:project-settings), you can get the crash log using the [Android Debug Bridge (ADB) tool](https://developer.android.com/studio/command-line/adb.html) and the `adb shell` command: ``` $ adb shell "run-as com.defold.example sh -c 'cat /data/data/com.defold.example/files/_crash'" > ./_crash ``` #### iOS In iTunes, you can view/download an apps container. In the `Xcode -> Devices` window, you can also select the crash logs ## Symbolicate a callstack If you get a callstack from either a `_crash` file or a [log file](#manuals:debugging-game-and-system-logs), you can symbolicate it. This means translating each address in the callstack into a filename and line number, which in turn helps when finding out the root cause. It is important that you match the correct engine with the callstack, otherwise it's very likely to send you debugging the incorrect things! Use the flag [`--with-symbols`](#manuals:bob) when bundling with [bob](#manuals:bob) or check the "Generate debug symbols" checkbox from the bundle dialog in the editor: * iOS - the `dmengine.dSYM.zip` folder in `build/arm64-ios` contains the debug symbols for iOS builds. * macOS - the `dmengine.dSYM.zip` folder in `build/x86_64-macos` contains the debug symbols for macOS builds. * Android - the `projecttitle.apk.symbols/lib/` bundle output folder contains the debug symbols for the target architectures. * Linux - the executable contain the debug symbols. * Windows - the `dmengine.pdb` file in `build/x86_64-win32` contains the debug symbols for Windows builds. * HTML5 - the `dmengine.js.symbols` file in `build/js-web` or `build/wasm-web` contains the debug symbols for HTML5 builds. It is very important that your save the debug symbols somewhere for each public release you make of your game and that you know which release the debug symbols belong to. You will not be able to debug any native crashes if you do not have the debug symbols! Also, you should keep an unstripped version of the engine. This allows for the best symbolication of the callstack. ### Uploading symbols to Google Play You can [upload the debug symbols to Google Play](https://developer.android.com/studio/build/shrink-code#android_gradle_plugin_version_40_or_earlier_and_other_build_systems) so that any crashes logged in Google Play will show symbolicated call stacks. Zip the contents of the `projecttitle.apk.symbols/lib/` bundle output folder. The folder includes one or more sub folders with architecture names such as `arm64-v8a` and `armeabi-v7a`. ### Symbolicate an Android callstack 1. Get the engine from your build folder ```sh $ ls /build//[lib]dmengine[.exe|.so] ``` 2. Unzip to a folder: ```sh $ unzip dmengine.apk -d dmengine_1_2_105 ``` 3. Find the callstack address E.g. in the non symbolicated callstack it could look like this `#00 pc 00257224 libmy_game_name.so` Where *`00257224`* is the address 4. Resolve the address ```sh $ arm-linux-androideabi-addr2line -C -f -e dmengine_1_2_105/lib/armeabi-v7a/libdmengine.so _address_ ``` Note: If you get hold of a stack trace from the [Android logs](#manuals:debugging-game-and-system-logs), you might be able to symbolicate it using [ndk-stack](https://developer.android.com/ndk/guides/ndk-stack.html) ### Symbolicate an iOS callstack 1. If you are using Native Extensions, the server can provide the symbols (.dSYM) for you (pass `--with-symbols` to bob.jar) ```sh $ unzip /build/arm64-darwin/build.zip # it will produce a Contents/Resources/DWARF/dmengine ``` 2. If you're not using Native Extensions, download the vanilla symbols: ```sh $ wget http://d.defold.com/archive//engine/arm64-darwin/dmengine.dSYM ``` 3. Symbolicate using load address For some reason, simply putting the address from the callstack doesn't work (i.e. load address 0x0) ```sh $ atos -arch arm64 -o Contents/Resources/DWARF/dmengine 0x1492c4 ``` # Neither does specifying the load address directly ```sh $ atos -arch arm64 -o MyApp.dSYM/Contents/Resources/DWARF/MyApp -l0x100000000 0x1492c4 ``` Adding the load address to the address works: ```sh $ atos -arch arm64 -o MyApp.dSYM/Contents/Resources/DWARF/MyApp 0x1001492c4 dmCrash::OnCrash(int) (in MyApp) (backtrace_execinfo.cpp:27) ``` # Debugging on Android {#manuals:debugging-native-code-android} Here we describe how to debug a build using [Android Studio](https://developer.android.com/studio/), the official IDE for Google's Android operating system. ## Android Studio * Prepare the bundle by setting the `android.debuggable` option in *game.project* * Bundle the app in debug mode into a folder of choice. * Launch [Android Studio](https://developer.android.com/studio/) * Choose `Profile or debug APK` * Choose the apk bundle you just created * Select the main `.so` file, and make sure it has debug symbols * If it doesn't, upload an unstripped `.so` file. (size is around 20mb) * Path mappings help you remap where the individual paths from where the executable was built (in the cloud) to an actual folder on your local drive. * Select the .so file, then add a mapping your local drive * If you have access to the engine source, add a path mapping to that too. * Make sure to checkout the version you are currently debugging defold$ git checkout 1.2.148 * Press `Apply changes` * You should now see the source mapped in your project * Add a breakpoint * Press `Run` -> `Debug "Appname"` and invoke the code you meant to break into * You can now step in the callstack as well as inspect the variables ## Notes ### Native Extension job folder Currently, the workflow is a bit troublesome for development. This is because the job folder name is random for each build, making the path mapping invalid for each build. However, it works fine for a debugging session. The path mappings are stored in the project `.iml` file in the Android Studio project. It's possible to get the job folder from the executable ```sh $ arm-linux-androideabi-readelf --string-dump=.debug_str build/armv7-android/libdmengine.so | grep /job ``` The jobfolder is named like so `job1298751322870374150`, each time with a random number. # Debugging on iOS/macOS {#manuals:debugging-native-code-ios} Here we describe how to debug a build using [Xcode](https://developer.apple.com/xcode/), Apple's preferred IDE for developing for macOS and iOS. ## Xcode * Bundle the app by using bob, with the `--with-symbols` option ([more info](#manuals:debugging-native-code)): ```sh $ cd myproject $ wget http://d.defold.com/archive//bob/bob.jar $ java -jar bob.jar --platform armv7-darwin build --with-symbols --variant debug --archive bundle -bo build/ios -mp .mobileprovision --identity "iPhone Developer: Your Name (ID)" ``` * Install the app, either with `Xcode`, `iTunes` or [ios-deploy](https://github.com/ios-control/ios-deploy) ```sh $ ios-deploy -b .ipa ``` * Get the `.dSYM` folder (i.e the debug symbols) * If it's not using Native Extensions, you can download the `.dSYM` file from [d.defold.com](http://d.defold.com) * If you are using a native extension, then the `.dSYM` folder is generated when you build with [bob.jar](#manuals:bob). Only building is required (no archive or bundling): ```sh $ cd myproject $ unzip .internal/cache/arm64-ios/build.zip $ mv dmengine.dSYM .dSYM $ mv .dSYM/Contents/Resources/DWARF/dmengine .dSYM/Contents/Resources/DWARF/ ``` ### Create Project To properly debug, we need to have a project, and the source code mapped. We're not using this project to build things, only debug. * Create new Xcode project, choose the `Game` template * Choose a name (e.g. `debug`) and the default settings * Choose a folder to save the project into * Add your code to the app * Make sure the "Copy items if needed" is unchecked. * This is the end result * Disable the `Build` step * Set the `Deployment target` version so it's now larger than your device iOS version * Select the target device ### Launch the debugger You have a few options to debug an app 1. Either choose `Debug` -> `Attach to process...` and select the app from there 2. Or choose the `Attach to process by PID or Process name` 3. Start the app on the device 4. In `Edit Scheme` add the .app folder as the executable ### Debug symbols **To use lldb, the execution must be paused** * Add the `.dSYM` path to lldb ``` (lldb) add-dsym ``` * Verify that `lldb` read the symbols successfully ``` (lldb) image list ``` ### Path mappings * Add the engine source (change accordingly for your need) ``` (lldb) settings set target.source-map /Users/builder/ci/builds/engine-ios-64-master/build /Users/mathiaswesterdahl/work/defold (lldb) settings append target.source-map /private/var/folders/m5/bcw7ykhd6vq9lwjzq1mkp8j00000gn/T/job4836347589046353012/upload/videoplayer/src /Users/mathiaswesterdahl/work/projects/extension-videoplayer-native/videoplayer/src ``` * It's possible to get the job folder from the executable. The jobfolder is named `job1298751322870374150`, each time with a random number. ```sh $ dsymutil -dump-debug-map 2>&1 >/dev/null | grep /job ``` * Verify the source mappings ``` (lldb) settings show target.source-map ``` You can check what source file a symbol was originating from using ``` (lldb) image lookup -va ``` ### Breakpoints * Open a file in the project view, and set a breakpoint ## Notes ### Check UUID of binary In order for the debugger to accept the `.dSYM` folder, the UUID need to match the UUID of the executable being debugged. You can check the UUID like so: ```sh $ dwarfdump -u ``` # Game and system log {#manuals:debugging-game-and-system-logs} The game log shows all of the output from the engine, native extensions and your game logic. The [print()](https://defold.com/ref/stable/base/#print:...) and [pprint()](https://defold.com/ref/stable/builtins/?q=pprint#pprint:v) commands can be used from your scripts and Lua modules to show information in the game log. You can use the functions in the [`dmLog` namespace](https://defold.com/ref/stable/dmLog/) to write to the game log from native extensions. The game log can be read from the editor, from a terminal window, using platform specific tools or from a log file. System logs are generated by the operating system and it can provide additional information that can help you pinpoint a problem. The system logs can contain stack traces for crashes and low memory warnings. Console/on-screen logging only shows information in Debug builds. In Release builds the console log is empty, but you can enable file logging in Release by setting the project setting "Write Log File" to "Always". See details below. ## Reading the game log from the editor When you run your game locally from the editor or connected to the [mobile development app](#manuals:dev-app) all of the output will be shown in the console pane of the editor: ## Reading the game log from the terminal When you run a Defold game from the terminal the log will show in the terminal window itself. On Windows and Linux you type the name of the executable in the terminal to start the game. On macOS you need to launch the engine from within the .app file: ``` $ > ./mygame.app/Contents/MacOS/mygame ``` ## Reading game and system logs using platform specific tools ### HTML5 Logs can be read using the developer tools provided by most browsers. * [Chrome](https://developers.google.com/web/tools/chrome-devtools/console) - Menu > More Tools > Developer Tools * [Firefox](https://developer.mozilla.org/en-US/docs/Tools/Browser_Console) - Tools > Web Developer > Web Console * [Edge](https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide/console) * [Safari](https://support.apple.com/guide/safari-developer/log-messages-with-the-console-dev4e7dedc90/mac) - Develop > Show JavaScript Console ### Android You can use the Android Debug Bridge (ADB) tool to view the game and system log. The `adb` command line tool is an easy to use and versatile program that is used to interact with Android devices. You can download and install `adb` as part of the Android SDK Platform-Tools, for Mac, Linux or Windows. Download the Android SDK Platform-Tools from: https://developer.android.com/studio/releases/platform-tools. You find the *adb* tool in */platform-tools/*. Alternatively, platform specific packages can be installed through respective package managers. On Ubuntu Linux: ``` $ sudo apt-get install android-tools-adb ``` On Fedora 18/19: ``` $ sudo yum install android-tools ``` On macOS (Homebrew) ``` $ brew cask install android-platform-tools ``` You can verify that `adb` works by connecting your Android device to your computer via USB and issue the following command: ``` $ adb devices List of devices attached 31002535c90ef000 device ``` If your device does not show up, verify that you have enabled *USB debugging* on the Android device. Open the device *Settings* and look for *Developer options* (or *Development*). Once installed and setup, connect your device with USB, open a terminal and run: ```txt $ cd /platform-tools/ $ adb logcat ``` The device will then dump all the output to the current terminal, along with any prints from the game. If you want to see only Defold application outputs use this command: ```txt $ cd /platform-tools/ $ adb logcat -s defold --------- beginning of /dev/log/system --------- beginning of /dev/log/main I/defold ( 6210): INFO:DLIB: SSDP started (ssdp://192.168.0.97:58089, http://0.0.0.0:38637) I/defold ( 6210): INFO:ENGINE: Defold Engine 1.2.50 (8d1b912) I/defold ( 6210): INFO:ENGINE: Loading data from: I/defold ( 6210): INFO:ENGINE: Initialized sound device 'default' I/defold ( 6210): D/defold ( 6210): DEBUG:SCRIPT: Hello there, log! ... ``` ### iOS You have multiple options to read game and system logs on iOS: 1. You can use the [Console tool](https://support.apple.com/guide/console/welcome/mac) to read game and system log. 2. You can use the LLDB debugger to attach 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 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: ```txt $ ios-deploy --debug --bundle # NOTE: not the .ipa file ``` 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). ## Reading the game log from the log file Use the project setting "Write Log File" in *game.project* to control file logging: - "Never": Do not write a log file. - "Debug": Write a log file only for Debug builds. - "Always": Write a log file for both Debug and Release builds. When enabled, any game output will be written to disk to a file named "`log.txt`". Here is how you extract the file if you run the game on device: iOS : Connect your device to a computer with macOS and Xcode installed. Open Xcode and go to `Window ▸ Devices and Simulators`. Select your device in the list, then select the relevant app in the *Installed Apps* list. Click the cog icon below the list and select `Download Container...`. Once the container has been extracted it will be shown in *Finder*. Right click the container and select `Show Package Content`. Locate the file "`log.txt`", which should be located in "`AppData/Documents/`". 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). # Optimizing a Defold game {#manuals:optimization} It is important to understand the technical constraints of your target platforms and to design, implement and optimize your game to meet these requirements. For most platforms there are several aspects to consider: * [Game size](#manuals:optimization-size) - What is the maximum acceptable size of the game bundle and how can you make the game as small as possible without compromising on quality? * [Runtime speed](#manuals:optimization-speed) - What is the performance of the target platform and how can you make the game run with a stable frame rate at minimal CPU and/or GPU usage? * [Memory usage](#manuals:optimization-memory) - What are the memory constraints of the target platform and how can you reduce memory usage? * [Battery usage](#manuals:optimization-battery) - This is mainly a focus area if you are targeting mobile/handheld devices. # Optimizing game size {#manuals:optimization-size} The size of your game can be a critical success factor for platforms such as web and mobile, while it is of less importance on desktop and consoles where disk space is cheap and often plentiful. ### iOS and Android Apple and Google has defined application size limits when downloading over mobile networks (as opposed to downloading over Wifi). For Android this limit is 200 MB for apps published with [app bundles](https://developer.android.com/guide/app-bundle#size_restrictions). For iOS users will get a warning if the application is larger than 200 MB, but can still proceed to download it. According to a 2017 study it was shown that "For every 6 MB increase to an APK's size, we see a decrease in the install conversion rate of 1%." ([source](https://medium.com/googleplaydev/shrinking-apks-growing-installs-5d3fcba23ce2)) ### HTML5 Poki and many other web game platforms recommend that the initial download should be no larger than 5 MB. Facebook has a recommendation that a Facebook Instant Game should start in less than 5 seconds and preferably less than 3 seconds. What this means for actual application size is not clearly defined but we are talking size in the range of up to 20 MB. Playable ads are usually limited to between 2 and 5 MB depending on the ad network. ## Size optimization strategies You can optimize the application size in two ways; by reducing the size of the engine and/or by reducing the size of the game assets. To get a better understanding of what makes up the size of your application you can [generate a build report](#manuals:bundling) when bundling. It is quite common that sounds and graphics is what takes up the bulk of the size of any game. Defold will create a dependency tree when building and bundling your application. The build system will start from the bootstrap collection specified in the *game.project* file and inspect every referenced collection, game object and component to build a list of the assets that are in use. It is only these assets that will get included in the final application bundle. Anything not directly referenced will get excluded. While it is good to know that unused assets will not be included you as a developer still needs to consider what goes into the final application and the size of the individual assets and the total size of the application bundle. ## Optimize engine size A quick way to reduce the engine size is to remove functionality in the engine that you do not use. This is done [application manifest file](#manuals:app-manifest) where it is possible to remove engine components that you do not need. Examples: * Physics - If your game does not make use of Box2D or Bullet3D physics then it is strongly advised to remove the physics engines * LiveUpdate - If your game does not use LiveUpdate it can be removed * Image loaded - If your game does not manually load and decode images using `image.load()` * BasisU - If your game has few textures, compare the build size without BasisU (removed via app manifest) and without texture compression versus a build with BasisU and compressed textures. For games with limited textures, it might be more beneficial to reduce the binary size and skip texture compression. Additionally, not using the transcoder can lower the amount of memory required to run your game. ## Optimize asset size The biggest wins in terms of asset size optimizations are usually gained by reducing the size of sounds and textures. ### Optimize sounds Defold supports these formats: * .wav * .ogg * .opus Sounds files must be using 16-bit samples. Our sound decoders will up/downscale sounds sample rates as needed for the current sound device. Shorter sounds like sound effects are often compressed harder, whereas music files have less compression. No compression is done by Defold, so the developer will have to handle that specifically for each audio format. You can edit the sounds in an external sound editor software (or command line using e.g. [ffmpeg](https://ffmpeg.org)) to reduce the quality or convert between formats. Also consider converting sounds from stereo to mono to further reduce the size of the content. ### Optimize textures You have several options when it comes to optimizing the textures used by your game, but the first thing to do is to check the size of the images that gets added to an atlas or used as a tilesource. You should never use a larger size on the images than is actually needed in your game. Importing large images and scaling them down to the appropriate size is a waste of texture memory and should be avoided. Start by adjusting the size of the images using external image editing software to the actual size needed in your game. For things such as background images it might also be ok to use a small image and scale it up to the desired size. Once you have the images down to the correct size and added to atlases or used in tilesources you also need to consider the size of the atlases themselves. The maximum atlas size that can be used varies between platforms and graphics hardware. [This forum posts](https://forum.defold.com/t/texture-management-in-defold/8921/17?u=britzl) suggests several tips on how to resize multiple images using scripts or third party software. * Max texture size on HTML5 reported to the [Web3D Survey project](https://web3dsurvey.com/webgl/parameters/MAX_TEXTURE_SIZE) * Max texture size on iOS: * iPad: 2048x2048 * iPhone 4: 2048x2048 * iPad 2, 3, Mini, Air, Pro: 4096x4096 * iPhone 4s, 5, 6+, 6s: 4096x4096 * Max texture size on Android varies greatly but in general all reasonably new devices support at least 4096x4096. If an atlas is too large you need to either split it into several smaller atlases, use multi-page atlases or scale the entire atlas using a texture profile. The texture profile system in Defold allows you to not only scale entire atlases but also to apply compression algorithms to reduce the size of the atlas on disk. You can [read more about texture profiles in the manual](#manuals:texture-profiles). If you don’t know what to use, try to start with these settings as a starting point for further customizations: * mipmaps: false * premultiply_alpha: true * format: TEXTURE_FORMAT_RGBA * compression_level: NORMAL * compression_type: COMPRESSION_TYPE_BASIS_UASTC You can read more about how to optimize and manage textures in [this forum post](https://forum.defold.com/t/texture-management-in-defold/8921). ### Optimize fonts The size of your fonts will be smaller if you specify what symbols you are going to use and set this in [Characters](#manuals:font) instead of using the All Chars checkbox. ### Exclude content for download on demand Another way of reducing initial application size is to exclude parts of the game content from the application bundle and download it on demand. Defold provides a system called Live Update for excluding content for download on demand. Excluded content can be anything from entire levels to unlockable characters, skins, weapons or vehicles. If your game has a lot of content, organize the loading process so that the bootstrap collection and the first level collection include the bare minimum resources required for that level. You achieve this by using collection proxies or factories with the "Exclude" checkbox enabled. Split resources according to the player's progress. This approach ensures efficient resource loading and keeps initial memory usage low. Learn more in the [Live Update manual](#manuals:live-update). ## Android specific size optimizations Android builds must support both 32-bit and 64-bit CPU architectures. When you [bundle for Android](#manuals:android) you can specify which CPU architectures to include: Google Play has support for [multiple APKs](https://developer.android.com/google/play/publishing/multiple-apks) per release of a game, which means that you can reduce the application size by generating two APKs, one per CPU architecture, and uploading both to Google Play. You can also make use of a combination of [APK Expansion Files](https://developer.android.com/google/play/expansion-files) and [Live Update content](#manuals:live-update) thanks to the [APKX extension in the Asset Portal](https://defold.com/assets/apkx/). # Optimizing runtime speed {#manuals:optimization-speed} Before trying to optimize a game with the goal to make it run at a stable high frame rate you need to know where your bottlenecks are. What is actually taking up most of the time in a frame of your game? Is it the rendering? Is it your game logic? Is it the scene graph? To figure this out it is recommended to use the built-in profiling tools. Use the [on-screen or web profiler](#manuals:profiling) to sample the performance of your game and then make a decision if and what to optimize. Once you have a better understanding of what takes time you can start addressing the problems. ## Reduce script execution time Reducing script execution time is needed if the profiler shows high values for the `Script` scope. As a general rule of thumb you should of course try to run as little code as possible every frame. Running a lot of code in `update()` and `on_input()` every frame is likely to have an impact on your game's performance, especially on low end devices. Some guidelines are: ### Use reactive code patterns Don't poll for changes if you can get a callback. Don't manually animate something or perform a task that can be handed over to the engine (e.g. `go.animate)()` vs manually animating something). ### Reduce garbage collection If you create loads of short lived objects such as Lua tables every frame this will eventually trigger the garbage collector of Lua. When this happens it can manifest itself as small hitches/spikes in frame time. Re-use tables where you can and really try to avoid creating Lua tables inside loops and similar constructs if possible. ### Prehash message and action ids If you do a lot of message handling or have many input events to deal with it is recommended to prehash the strings. Consider this piece of code: ```lua function on_message(self, message_id, message, sender) if message_id == hash("message1") then msg.post(sender, hash("message3")) elseif message_id == hash("message2") then msg.post(sender, hash("message4")) end end ``` In the above scenario the hashed string would be recreated every time a message is received. This can be improved by creating the hashed strings once and use the hashed versions when handling messages: ```lua local MESSAGE1 = hash("message1") local MESSAGE2 = hash("message2") local MESSAGE3 = hash("message3") local MESSAGE4 = hash("message4") function on_message(self, message_id, message, sender) if message_id == MESSAGE1 then msg.post(sender, MESSAGE3) elseif message_id == MESSAGE2 then msg.post(sender, MESSAGE4) end end ``` ### Prefer and cache URLs Message passing or in other ways addressing a game object or component can be done both by providing an id as a string or hash or as a URL. If a string or hash is used it will internally be translated into a URL. It is therefore recommended to cache URLs that are used often, to get the best possible performance out of the system. Consider the following: ```lua local pos = go.get_position("enemy") local pos = go.get_position(hash("enemy")) local pos = go.get_position(msg.url("enemy")) -- do something with pos ``` In all three cases the position of a game object with id `enemy` would be retrieved. In the first and second case the id (string or hash) would be converted into a URL before being used. This tells us that it's better to cache URLs and use the cached version for the best possible performance: ```lua function init(self) self.enemy_url = msg.url("enemy") end function update(self, dt) local pos = go.get_position(self.enemy_url) -- do something with pos end ``` ## Reduce time it takes to render a frame Reducing the time it takes to render a frame is needed if the profiler shows high values in the `Render` and `Render Script` scopes. There are several things to consider when trying to increase reduce the time it takes to render a frame: * Reduce draw calls - Read more about reducing draw calls in [this forum post](https://forum.defold.com/t/draw-calls-and-defold/4674) * Reduce overdraw * Reduce shader complexity - Read up on GLSL optimizations in [this Khronos article](https://www.khronos.org/opengl/wiki/GLSL_Optimizations). You can also modify the default shaders used by Defold (found in `builtins/materials`) and reduce shader precision to gain some speed on low end devices. All shaders are using `highp` precision and a change to for instance `mediump` can in some cases improve performance slightly. ## Reduce scene graph complexity Reducing the scene graph complexity is needed if the profiler shows high values in the `GameObject` scope and more specifically for the `UpdateTransform` sample. Some actions to take: * Culling - Disable game objects (and their components) if they aren't currently visible. How this is determined depends very much on the type of game. For a 2D game it can be as easy as always disabling game objects that are outside of a rectangular area. You can use a physics trigger to detect this or by partitioning your objects into buckets. Once you know which objects to disable or enable you do this by sending a `disable` or `enable` message to each game object. ## Frustum culling The render script can automatically ignore rendering of game object component that are outside of a defined bounding box (frustum). Learn more about Frustum Culling in the [Render Pipeline manual](#manuals:render). # Platform specific optimizations ## Android Device Performance Framework Android Dynamic Performance Framework is a set of APIs that allow games and to interact more directly with power and thermal systems of Android devices. It is possible to monitor the dynamic behavior on Android systems and optimize game performance at a sustainable level that doesn’t overheat devices. Use the [Android Dynamic Performance Framework extension](https://defold.com/extension-adpf/) to monitor and optimize performance in your Defold game for Android devices. # Optimize battery usage {#manuals:optimization-battery} Battery usage is mainly a concern if you are targeting mobile/handheld devices. High CPU or GPU usage will quickly drain battery and overheat the device. Refer to the manuals on how to [optimize runtime performance](#manuals:optimization-speed) of a game to learn how to reduce CPU and GPU usage. ## Disable accelerometer If you are creating a mobile game which doesn't make use of the device accelerometer it is recommended to [disable it in *game.project*](#manuals:project-settings) to reduce the number of generated input events. # Platform specific optimizations ## Android Device Performance Framework Android Dynamic Performance Framework is a set of APIs that allow games and to interact more directly with power and thermal systems of Android devices. It is possible to monitor the dynamic behavior on Android systems and optimize game performance at a sustainable level that doesn’t overheat devices. Use the [Android Dynamic Performance Framework extension](https://defold.com/extension-adpf/) to monitor and optimize performance in your Defold game for Android devices. # Optimizing memory usage {#manuals:optimization-memory} ## Texture compression The use of texture compression will not only reduce the size of resources within your game archive, but compressed textures may also reduce the amount of GPU memory required. ## Dynamic loading Most game have at least some content that is used infrequently. From a memory usage stand point it does not make sense to have such content loaded in memory at all times, but rather load and unload it when it is needed. This will obviously be a trade-off between having something readily accessible at the cost of runtime memory and loading something at the cost of loading time. Defold has several different ways of loading content dynamically: * [Collection proxies](#manuals:collection-proxy) * [Dynamic collection factories](#manuals:collection-factory) * [Dynamic factories](#manuals:factory) * [Live Update](#manuals:live-update) ## Optimize component counters Defold will allocate memory for components and resources once when a collection is created, to reduce memory fragmentation. The amount of memory that is allocated depends on the configuration of various components counters in *game.project*. Use the [profiler](#manuals:profiling) to get accurate component and resource usage and configure your game to use max values that are closer to the real count of components and resources. This will reduce the amount of memory your game is using (refer to information about component [max count optimizations](#manuals:project-settings)). ## Optimize GUI node count Optimize GUI node counts by setting the max number of nodes in the GUI file to only what is needed. The `Current Nodes` field of the [GUI component properties](#manuals:gui) will show the number of nodes used by the GUI component. ## Heap size (HTML5) The heap size of a Defold HTML5 game can be configured from the [`heap_size` field](#manuals:project-settings) in *game.project*. Make sure to optimize memory usage of your game and set a minimal heap size. For small games, 32 MB is an achievable heap size. For larger games, aim for 64–128 MB. If, for example, you're at 58 MB and further optimization isn't feasible, you can settle on 64 MB without overthinking it. There’s no strict target size — it depends on the game. Just aim for smaller sizes, ideally in steps of powers of two. To check current heap usage you can launch your game and play the game in the most "resource heavy" level or section and monitor memory usage: ```lua if html5 then local mem = tonumber(html5.run("HEAP8.length") / 1024 / 1024) print(mem) end ``` You can also open the developer tools of your browser and write the following in the console: ```js HEAP8.length / 1024 / 1024 ``` If the memory usage remains at 32 MB, that's great! If not, follow the steps to [optimize the size of the engine itself and large assets such as sounds and textures](#manuals:optimization-size). # Profiling {#manuals: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 frame profiler that is used in Defold is the [Remotery profiler by Celtoys](https://github.com/Celtoys/Remotery). ## The runtime visual profiler Debug builds feature a runtime visual profiler that displays live information rendered overlaid on top of the running application: ```lua function on_reload(self) -- Toggle the visual profiler on hot reload. profiler.enable_ui(true) end ``` The visual profiler provides a number of different function that can be used to change the way the visual profiler presents its data: ```lua profiler.set_ui_mode() profiler.set_ui_view_mode() profiler.view_recorded_frame() ``` Refer to a the [profiler API reference](https://defold.com/ref/stable/profiler/) for more information about the profiler functions. ## The web profiler While running a debug build of the game, an interactive web-based profiler can be accessed through a browser. ### Frame profiler The Frame profiler allows you to sample your game while it is running and analyze individual frames in detail. To access the profiler: 1. Start your game on your target device. 2. Select ` Debug ▸ Open Web Profiler` menu. The frame profiler is divided into several sections that all give different views into the running game. Press the Pause button in the top right corner to temporarily stop the profiler from updating the views. When you use multiple targets simultaneously, you can manually switch between them by changing the Connection Address field at the top of the page to match the Remotery profiler URL shown in the console when the target started: ``` INFO:ENGINE: Defold Engine 1.3.4 (80b1b73) INFO:DLIB: Initialized Remotery (ws://127.0.0.1:17815/rmt) INFO:ENGINE: Loading data from: build/default ``` Sample Timeline : The Sample Timeline will show the frames of data captured in the engine, one horizontal timeline per Thread. Main is the main thread where all of the game logic and most of the engine code is run. Remotery is for the profiler itself and Sound is for the sound mixing and playback thread. You can zoom in and out (using the mouse wheel) and select individual frames to see the details of a frame in the Frame 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. Global Properties : The Global Properties view shows a table of counters. They make it is easy to, for instance, track the number of draw calls or the number of components of a certain type. The LuaMem value is the amount of memory in kilobytes used by the Lua VM as reported by the Lua garbage collector. Memory is the amount of memory in kilobytes used by the engine. ### Resource profiler The Resource profiler allows you to inspect your game while it is running and analyze resource use in detail. To access the profiler: 1. Start your game on your target device. 2. Open a browser and browse to http://localhost:8002 The resource profiler is divided into 2 sections, one showing a hierarchical view of the collections, game objects and components currently instantiated in your game, and the other showing all currently loaded resources. Collection view : The collection view shows hierarchical list of all game objects and components currently instantiated in the game and from which collection they originate. This is a very useful tool when you need to dig into and understand what you have instanced in your game at any given time and from where the objects originate. Resources view : The resources view shows all resources currently loaded into memory, their size and the number of references to each resource. This is useful when optimizing memory usage in your application when you need to understand what is loaded into memory at any given time. ## 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. The builder will produce a file called "report.html" alongside the game bundle. Open the file in a web browser to inspect the report: 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. OpenGL profiler (macOS) : Part of the package "Additional Tools for Xcode" that you can download from Apple (select `Xcode ▸ Open Developer Tool ▸ More Developer Tools...` 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. Android Profiler (Android) : https://developer.android.com/studio/profile/android-profiler.html A set of profiling tools that captures real-time 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". Note: Since Android Studio 4.1 it is also possible to [run the profiling tools without starting Android Studio](https://developer.android.com/studio/profile/android-profiler.html#standalone-profilers). 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". # Ads {#manuals:ads} Ads has become a very common way of monetizing web and mobile games and it has turned into a billion dollar industry. As a developer you get paid based on the number of people watching the ads you show in your game. It is usually as simple as more viewers equals more money, but other factors also have an impact on how much you get paid: * The ad quality - relevant ads are more likely to get interaction and attention from your players. * The ad format - banner ads usually pay less while full screen ads viewed from start to to finish pays more. * The ad network - the amount you get paid varies from ad networks to ad network. CPM = Cost per mille. The amount an advertiser pays per one thousand views. The CPM varies between ad networks and ad formats. ## Formats There are many different kinds of ad formats that can be used in games. Some of the more common ones are banner, interstitial and reward ads: ### Banner ads Banner ads are text, image or video based and cover a relatively small part of the screen, usually at the top or bottom of the screen. Banner ads are very easy to implement and they fit very well with casual single screen games where it is easy to reserve an area of the screen for advertisements. Banner ads maximize exposure as users play your game without interruption. ### Interstitial ads Interstitial ads are large full screen experiences with animations and sometimes also interactive rich media content. Interstitial ads are typically shown in between levels or game sessions as it is a natural break in the game experience. Interstitial ads typically generate less views than banner ads, but the cost (CPM) is much higher than for banner ads, resulting in significant overall ad revenue. ### Rewarded ads Rewarded ads (also know as Incentivized ads) are optional and therefore less obtrusive than many other forms of ads. Rewarded ads are usually full screen experiences like interstitial ads. The user can choose a reward in exchange for viewing the ad - for instance loot, coins, lives, time or some other in-game currency or benefit. Rewarded ads usually has the highest cost (CPM), but the number of views is directly related to user opt-in rates. Rewarded ads will only generate great performance if the rewards are valuable enough and offered at the right time. ## Ad networks The [Defold Asset Portal](https://defold.com/tags/stars/ads/) contains several assets which integrate with ad providers: * [AdMob](https://defold.com/assets/admob-defold/) - Show ads using the Google AdMob network. * [Enhance](https://defold.com/assets/enhance/) - Supports a number of different ad networks. Requires an additional post-build step. * [Facebook Instant Games](https://defold.com/assets/facebookinstantgames/) - Show ads in your Facebook Instant Game. * [IronSource](https://defold.com/assets/ironsource/) - Show ads using the IronSource Ad network. * [Unity Ads](https://defold.com/assets/defvideoads/) - Show ads using the Unity Ads network. # How to integrate ads in your game When you have decided on an ad network to integrate in your game you need to follow the installation and usage instructions for that particular asset. What you typically do is to first add the extension as a [project dependency](#manuals:libraries). Once you have the asset added to your project you can proceed with the integration and call the functions specific to the asset to load and show ads. # Combining ads and in-app purchases It is quite common in mobile games to offer an [In-app purchase](#manuals:iap) to get rid of ads permanently. ## Learn more There are many online resources to learn from when it comes to optimizing ad revenue: * Google AdMob [Monetize mobile games with ads](https://admob.google.com/home/resources/monetize-mobile-game-with-ads/) * Game Analytics [Popular ad formats and how to use them](https://gameanalytics.com/blog/popular-mobile-game-ad-formats.html) * deltaDNA [Ad serving in games: 10 expert tips](https://deltadna.com/blog/ad-serving-in-games-10-tips/) # Android development {#manuals:android} Android devices allows you to freely run your own apps on them. It is very easy to build a version of your game and copy it onto an Android device. This manual explains the steps involved in bundling your game for Android. During development, running your game through the [development app](#manuals:dev-app) is often preferred since it allows you to hot reload content and code directly to your device. ## Android and Google Play signing process Android requires that all APKs be digitally signed with a certificate before they are installed on a device or updated. If you use Android App Bundles, you need to sign only your app bundle before you upload it to the Play Console, and [Play App Signing](https://developer.android.com/studio/publish/app-signing#app-signing-google-play) takes care of the rest. However, you can also manually sign your app for upload to Google Play, other app stores and for distribution outside of any store. When you create an Android application bundle from the Defold editor or the [command line tool](#manuals:bob) you can provide a keystore (containing your certificate and key) and keystore password which will be used when signing your application. If you don't, Defold generates a debug keystore and uses it when signing the application bundle. You should **never** upload your application to Google Play if it was signed using a debug keystore. Always use a dedicated keystore which you have created yourself. ## Creating a keystore The Android signing process in Defold changed in version 1.2.173 from using a stand-alone key and certificate to a keystore. [More information in this forum post](https://forum.defold.com/t/upcoming-change-to-the-android-build-pipeline/66084). You can create a keystore [using Android Studio](https://developer.android.com/studio/publish/app-signing#generate-key) or from a terminal/command prompt: ```bash keytool -genkey -v -noprompt -dname "CN=John Smith, OU=Area 51, O=US Air Force, L=Unknown, ST=Nevada, C=US" -keystore mykeystore.keystore -storepass 5Up3r_53cR3t -alias myAlias -keyalg RSA -validity 9125 ``` This will create a keystore file named `mykeystore.keystore` containing a key and certificate. Access to key and certificate will be protected by the password `5Up3r_53cR3t`. The key and certificate will be valid for 25 years (9125 days). The generated key and certificate will be identified by the alias `myAlias`. Make sure to store the keystore and associated password somewhere safe. If you sign and upload your applications to Google Play yourself and the keystore or keystore password is lost there is no way for you to update the application on Google Play. You can avoid this by using Google Play App Signing and let Google sign your applications for you. ## Creating an Android application bundle The editor lets you easily create a stand alone application bundle for your game. Before bundling you can specify what icon(s) to use for the app, set version code etc in the *game.project* [project settings file](#manuals:project-settings). To bundle select `Project ▸ Bundle... ▸ Android Application...` from the menu. If you want the editor to automatically create random debug certificates, leave the *Keystore* and *Keystore password* fields empty: If you want to sign your bundle with a particular keystore, specify the *Keystore* and *Keystore password*. The *Keystore* is expected to have the `.keystore` file extension while the password is expected to be stored in a text file with the `.txt` extension. It is also possible to specify a *Key password* if the key in the keystore uses a different password than the keystore itself: Defold supports the creation of both APK and AAB files. Select APK or AAB from the Bundle Format drop down. Press `Create Bundle` when you have configured the application bundle settings. You will then be prompted to specify where on your computer the bundle will be created. ## Build variants When you bundle a game, you need to choose what type of engine you wish to use. You have three basic options: * Debug * Release * Headless These different versions are also referred to as `Build variants` When you choose `Project ▸ Build` you'll always get the debug version. ### Debug This type of executable is typically used during development of a game as it has several useful debugging features included: * Profiler - Used for gathering performance and usage counters. Learn how to use the profiler in the [Profiling manual](#manuals:profiling). * Logging - The engine will log system information, warnings and errors when logging is enabled. The engine will also output logs from the Lua `print()` function and from native extensions logging using `dmLogInfo()`, `dmLogError()` and so on. Learn how to read these logs in the [Game and System Logs manual](#manuals:debugging-game-and-system-logs). * Hot reload - Hot-reload is a powerful feature which lets a developer reload resource while the game is running. Learn how to use this in the [Hot-Reload manual](#manuals:hot-reload). * Engine services - It is possible to connect to and interact with a debug version of a game through a number of different open TCP ports and services. The services include the hot-reload feature, remote log access and the profiler mentioned above, but also other services to remotely interact with the engine. Learn more about the engine services [in the developer documentation](https://github.com/defold/defold/blob/dev/engine/docs/DEBUG_PORTS_AND_SERVICES.md). ### Release This variant has the debugging features disabled. This options should be chosen when the game is ready to be released to the app store or in other ways shared with players. It is not recommended to release a game with the debugging features enabled for a number of reasons: * The debugging features take up a little bit of size in the binary, and [it is a best practice to try to keep the binary size of a released game as small as possible](#manuals:optimization). * The debugging features takes a little bit of CPU time as well. This can impact the performance of the game if a user has a low-end hardware. On mobile phones the increased CPU usage will also contribute to heating and battery drain. * The debugging features may expose information about the game that is not intended for the eyes of the players, either from a security, cheating or fraud perspective. ### Headless This executable runs without any graphics and sound. It means that you can run the game unit/smoke tests on a CI server, or even have it as a game server in the cloud. ### Installing an Android application bundle #### Installing an APK An *`.apk`* file can be copied to your device with the `adb` tool, or to Google Play via the [Google Play developer console](https://play.google.com/apps/publish/). The `adb` command line tool is an easy to use and versatile program that is used to interact with Android devices. You can download and install `adb` as part of the Android SDK Platform-Tools, for Mac, Linux or Windows. Download the Android SDK Platform-Tools from: https://developer.android.com/studio/releases/platform-tools. You find the *adb* tool in */platform-tools/*. Alternatively, platform specific packages can be installed through respective package managers. On Ubuntu Linux: ``` $ sudo apt-get install android-tools-adb ``` On Fedora 18/19: ``` $ sudo yum install android-tools ``` On macOS (Homebrew) ``` $ brew cask install android-platform-tools ``` You can verify that `adb` works by connecting your Android device to your computer via USB and issue the following command: ``` $ adb devices List of devices attached 31002535c90ef000 device ``` If your device does not show up, verify that you have enabled *USB debugging* on the Android device. Open the device *Settings* and look for *Developer options* (or *Development*). ``` $ adb install Defold\ examples.apk 4826 KB/s (18774344 bytes in 3.798s) pkg: /data/local/tmp/my_app.apk Success ``` #### Installing an APK using editor You can install and launch an *`.apk`* file using the editor's "Install on connected device" and "Launch installed app" check-boxes in the Bundle dialog: For this feature to work, you will need ADB installed and *USB debugging* enabled on the connected device. If the editor can't detect the install location of the ADB command line tool, you will need to specify it in [Preferences](#manuals:editor-preferences). #### Installing an AAB An *.aab* file can be uploaded to Google Play via the [Google Play developer console](https://play.google.com/apps/publish/). It is also possible to generate an *`.apk`* file from an *.aab* file to install it locally using the [Android bundletool](https://developer.android.com/studio/command-line/bundletool). ## Permissions The Defold engine requires a number of different permissions for all engine features to work. The permissions are defined in the `AndroidManifest.xml`, specified in the *game.project* [project settings file](#manuals:project-settings). You can read more about Android permissions in [the official docs](https://developer.android.com/guide/topics/permissions/overview). The following permissions are requested in the default manifest: ### android.permission.INTERNET and android.permission.ACCESS_NETWORK_STATE (Protection level: normal) Allows applications to open network sockets and access information about networks. These permission are needed for internet access. ([Android official docs](https://developer.android.com/reference/android/Manifest.permission#INTERNET)) and ([Android official docs](https://developer.android.com/reference/android/Manifest.permission#ACCESS_NETWORK_STATE)). ### android.permission.WAKE_LOCK (Protection level: normal) Allows using PowerManager WakeLocks to keep processor from sleeping or screen from dimming. This permission is needed to temporarily prevent the device from sleeping while receiving a push notification. ([Android official docs](https://developer.android.com/reference/android/Manifest.permission#WAKE_LOCK)) ## Using AndroidX AndroidX is a major improvement to the original Android Support Library, which is no longer maintained. AndroidX packages fully replace the Support Library by providing feature parity and new libraries. Most of the Android extensions in the [Asset Portal](https://defold.com/assets) support AndroidX. If you do not wish to use AndroidX you can explicitly disable it in favour of the old Android Support Library by checking the `Use Android Support Lib` in the [application manifest](#manuals:app-manifest). ## FAQ #### Q: Is it possible to hide the navigation and status bars on Android? A: Yes, set the *immersive_mode* setting in the *Android* section of your *game.project* file. This lets your app take over the whole screen and capture all touch events on the screen. #### Q: Why am I'm getting "Failure [INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES]" when installing a Defold game on device? A: Android detects that you try to install the app with a new certificate. When bundling debug builds, each build will be signed with a temporary certificate. Uninstall the old app before installing the new version: ``` $ adb uninstall com.defold.examples Success $ adb install Defold\\ examples.apk 4826 KB/s (18774344 bytes in 3.798s) pkg: /data/local/tmp/Defold examples.apk Success ``` #### Q: Why am I getting errors about conflicting properties in AndroidManifest.xml when building with certain extensions? A: This can happen when two or more extensions provide an Android Manifest stub containing the same property tag but with different values. This has for instance happened with Firebase and AdMob. The build error looks similar to this: ``` SEVERE: /tmp/job4531953598647135356/upload/AndroidManifest.xml:32:13-58 Error: Attribute property#android.adservices.AD_SERVICES_CONFIG@resource value=(@xml/ga_ad_services_config) from AndroidManifest.xml:32:13-58 is also present at AndroidManifest.xml:92:13-59 value=(@xml/gma_ad_services_config). Suggestion: add 'tools:replace="android:resource"' to element at AndroidManifest.xml to override. ``` You can read more about the issue and the workaround in reported Defold issue [#9453](https://github.com/defold/defold/issues/9453#issuecomment-2367367269) and Google issue [#327696048](https://issuetracker.google.com/issues/327696048?pli=1). # Inter-app communication {#manuals:iac} Applications can on most operating systems be launched in several ways: * From the list of installed applications * From an application specific link * From a push notification * As the final step of an installation process. In the case when the application is launched from a link, notification or when installed it is possible to pass additional arguments such as an install referrer when installing or a deep-link when launching from an application specific link or notification. Defold provides a unified way to get the information about how the application was invoked using a native extensions. ## Installing the extension To start using the Inter-app communication extension you need to add it as a dependency to your *game.project* file. The latest stable version is available with the dependency URL: ``` https://github.com/defold/extension-iac/archive/master.zip ``` We recommend using a link to a zip file of a [specific release](https://github.com/defold/extension-iac/releases). ## Using the extension The API is very easy to use. You provide the extension with a listener function and react to listener callbacks. ``` local function iac_listener(self, payload, type) if type == iac.TYPE_INVOCATION then -- This was an invocation print(payload.origin) -- origin may be empty string if it could not be resolved print(payload.url) end end function init(self) iac.set_listener(iac_listener) end ``` Full documentation of the API is available on the [extension GitHub page](https://defold.github.io/extension-iac/). # iOS development {#manuals:ios} Bundling a game for iOS is available only on Mac version of the Defold Editor. iOS requires that _any_ app that you build and want to run on your phone or tablet _must_ be signed with an Apple-issued certificate and provisioning profile. This manual explains the steps involved in bundling your game for iOS. During development, running your game through the [development app](#manuals:dev-app) is often preferred since it allows you to hot reload content and code directly to your device. ## Apple's code signing process The security associated with iOS apps consists of several components. You can get access to the required tools by singing up to the [Apple's iOS Developer Program](https://developer.apple.com/programs/). When you have enrolled, go to the [Apple's Developer Member Center](https://developer.apple.com/membercenter/index.action). The section *Certificates, Identifiers & Profiles* contains all the tools that you need. From here you can create, delete and edit: Certificates : Apple-issued cryptographic certificates that identify you as a developer. You can create development or production certificates. Developer certificates allow you to test certain features such as the in-app purchase mechanism in a sandbox test environment. Production certificates are used to sign the final app for upload to the App Store. You need a certificate to sign apps before you can put them on your device for testing. Identifiers : Identifiers for various uses. It is possible to register wildcard identifiers (i.e. `some.prefix.*`) which can be used with several apps. App IDs can contain Application Service information, like if the app enables Passbook integration, the Game Center, etc. Such App IDs cannot be wildcard identifiers. For Application Services to function, your application's *bundle identifier* must match the App ID identifier. Devices : Each development device needs to be registered with their UDID (Unique Device IDentifier, see below). Provisioning Profiles : Provisioning profiles associate certificates with App IDs and a list of devices. They tell which app by what developer is allowed to be on what devices. When signing your games and apps in Defold, you need a valid certificate and a valid provisioning profile. Some of the things you can do on the Member Center homepage you can also perform from inside the Xcode development environment---if you have that installed. Device identifier (UDID) : The UDID for an iOS device can be found by connecting the device to a computer via wifi or cable. Open Xcode and select `Window ▸ Devices and Simulators`. The serial number and identifier are displayed when you select your device. If you don't have Xcode installed you can find the identifier in iTunes. Click on the devices symbol and select your device. 1. On the *Summary* page, locate the *Serial Number*. 2. Click the *Serial Number* once so the field changes into *UDID*. If you click repeatedly, several pieces of information about the device will show up. Just continue to click until *UDID* shows. 3. Right-click the long UDID string and select `Copy` to copy the identifier to the clipboard so you can easily paste it into the UDID field when registering the device on Apple's Developer Member Center. ## Developing using a free Apple developer account Since Xcode 7, anyone can install Xcode and do on-device development for free. You don't have to sign up for the iOS Developer Program. Instead, Xcode will automatically issue a certificate for you as a developer (valid for 1 year) and a provisioning profile for your app (valid for one week) on your specific device. 1. Connect your device. 2. Install Xcode. 3. Add a new account to Xcode and sign in with your Apple ID. 4. Create a new project. The simplest "Single View App" works fine. 5. Select your "Team" (auto created for you) and give the app a bundle identifier. Make a note of the bundle identifier as you must use the same bundle identifier in your Defold project. 6. Make sure that Xcode has created a *Provisioning Profile* and *Signing Certificate* for the app. 7. Build the app on your device. The first time, Xcode will ask you to enable Developer mode and will prepare the device with debugger support. This may take a while. 8. When you have verified that the app works, find it on your disk. You can see the build location in the Build report in the "Report Navigator". 9. Locate the app, right-click it and select `Show Package Contents`. 10. Copy the file "embedded.mobileprovision" to some place on your drive where you will find it. This provision file can be used together with your code signing identity to sign apps in Defold for one week. When the provision expires, you need to build the app again in Xcode and get a new temporary provision file as described above. ## Creating an iOS application bundle When you have the code signing identity and provisioning profile, you are ready to create a stand alone application bundle for your game from the editor. Simply select `Project ▸ Bundle... ▸ iOS Application...` from the menu. Select your code signing identity and browse for your mobile provisioning file. Select which architectures (32 bit, 64 bit and the iOS simulator) to bundle for as well as the variant (Debug or Release). You can optionally uncheck the `Sign application` checkbox to skip the signing process and then manually sign at a later stage. You **must** uncheck the `Sign application` checkbox when testing your game on the iOS simulator. You will be able to install the application but it will not boot. Press *Create Bundle* and you will then be prompted to specify where on your computer the bundle will be created. You specify what icon to use for the app, the launch screen storyboard and so forth in the *game.project* project settings file in the [iOS section](#manuals:project-settings). ## Build variants When you bundle a game, you need to choose what type of engine you wish to use. You have three basic options: * Debug * Release * Headless These different versions are also referred to as `Build variants` When you choose `Project ▸ Build` you'll always get the debug version. ### Debug This type of executable is typically used during development of a game as it has several useful debugging features included: * Profiler - Used for gathering performance and usage counters. Learn how to use the profiler in the [Profiling manual](#manuals:profiling). * Logging - The engine will log system information, warnings and errors when logging is enabled. The engine will also output logs from the Lua `print()` function and from native extensions logging using `dmLogInfo()`, `dmLogError()` and so on. Learn how to read these logs in the [Game and System Logs manual](#manuals:debugging-game-and-system-logs). * Hot reload - Hot-reload is a powerful feature which lets a developer reload resource while the game is running. Learn how to use this in the [Hot-Reload manual](#manuals:hot-reload). * Engine services - It is possible to connect to and interact with a debug version of a game through a number of different open TCP ports and services. The services include the hot-reload feature, remote log access and the profiler mentioned above, but also other services to remotely interact with the engine. Learn more about the engine services [in the developer documentation](https://github.com/defold/defold/blob/dev/engine/docs/DEBUG_PORTS_AND_SERVICES.md). ### Release This variant has the debugging features disabled. This options should be chosen when the game is ready to be released to the app store or in other ways shared with players. It is not recommended to release a game with the debugging features enabled for a number of reasons: * The debugging features take up a little bit of size in the binary, and [it is a best practice to try to keep the binary size of a released game as small as possible](#manuals:optimization). * The debugging features takes a little bit of CPU time as well. This can impact the performance of the game if a user has a low-end hardware. On mobile phones the increased CPU usage will also contribute to heating and battery drain. * The debugging features may expose information about the game that is not intended for the eyes of the players, either from a security, cheating or fraud perspective. ### Headless This executable runs without any graphics and sound. It means that you can run the game unit/smoke tests on a CI server, or even have it as a game server in the cloud. ## Installing and launching bundle on a connected iPhone You can install and launch the built bundle using editor's "Install on connected device" and "Launch installed app" check-boxes in the Bundle dialog: You need [ios-deploy](https://github.com/ios-control/ios-deploy) command lint tool installed for this feature to work. The simplest way to install it is using Homebrew: ``` $ brew install ios-deploy ``` If the editor can't detect the install location of the ios-deploy tool, you will need to specify it in [Preferences](#manuals:editor-preferences). ### Creating a storyboard You create a storyboard file using Xcode. Start Xcode and create a new project. Select iOS and Single View App: Click Next and proceed to configure your project. Enter a Product Name: Click Create to finish the process. Your project is now created and we can proceed to create the storyboard: Drag and drop an image to import it to the project. Next select `Assets.xcassets` and drop the image to `Assets.xcassets`: Open `LaunchScreen.storyboard` and click on the plus button (`+`). Type "imageview" in the dialog to find the ImageView component. Drag the Image View component onto the storyboard: Select the image you previously added to `Assets.xcassets` from the Image dropdown: Position the image and make any other adjustments you need, perhaps adding a Label or some other UI element. When you are done set the active scheme to "Build -> Any iOS Device (`arm64`, `armv7`)"(or "Generic iOS Device") and select Product -> Build. Wait for the build process to finish. If you have only `arm64` option in "Any iOS Device (arm64)" change `iOS Deployment target` to 10.3 in "Project -> Basic -> Deployment" settings. It will make your storyboard compatible with `armv7` devices (for example iPhone5c) If you use images in the storyboard they will not be included in your `LaunchScreen.storyboardc` automatically. Use `Bundle Resources` field in *game.project* to include resources. For example, create folder `LaunchScreen` in Defold project and folder `ios` inside (`ios` folder needed to include these files only for ios bundles), then put your files in `LaunchScreen/ios/`. Add this path in `Bundle Resources`. The last step is to copy the compiled `LaunchScreen.storyboardc` file to your Defold project. Open Finder at the following location and copy the `LaunchScreen.storyboardc` file to your Defold project: /Library/Developer/Xcode/DerivedData/YOUR-PRODUCT-NAME-cbqnwzfisotwygbybxohrhambkjy/Build/Intermediates.noindex/YOUR-PRODUCT-NAME.build/Debug-iphonesimulator/YOUR-PRODUCT-NAME.build/Base.lproj/LaunchScreen.storyboardc Forum user Sergey Lerg has put together [a video tutorial showing the process](https://www.youtube.com/watch?v=6jU8wGp3OwA&feature=emb_logo). Once you have the storyboard file you can reference it from *game.project*. ### Creating an icon asset catalog This is required from Defold 1.2.175. Using an asset catalog is Apple's preferred way to manage your application's icons. In fact it is the only way to provide the icon used in the App Store listing. You create an asset catalog in the same way as a storyboard, using Xcode. Start Xcode and create a new project. Select iOS and Single View App: Click Next and proceed to configure your project. Enter a Product Name: Click Create to finish the process. Your project is now created and we can proceed to create the asset catalog: Drag and drop images to the empty boxes representing the different supported icon sizes: Do not add any icons for Notifications, Settings or Spotlight. When you are done, set the active scheme to "Build -> Any iOS Device (arm64)"(or "Generic iOS Device") and select `Product` -> `Build`. Wait for the build process to finish. Make sure that you build for "Any iOS Device (arm64)" or "Generic iOS Device" otherwise you will get `ERROR ITMS-90704` error when uploading your build. The last step is to copy the compiled `Assets.car` file to your Defold project. Open Finder at the following location and copy the `Assets.car` file to your Defold project: /Library/Developer/Xcode/DerivedData/YOUR-PRODUCT-NAME-cbqnwzfisotwygbybxohrhambkjy/Build/Products/Debug-iphoneos/Icons.app/Assets.car Once you have the asset catalog file you can reference it and the icons from *game.project*: The App Store icon does not have to be referenced from *game.project*. It is automatically extracted from the `Assets.car` file when uploading to iTunes Connect. ## Installing an iOS application bundle The editor writes an *.ipa* file which is an iOS application bundle. To install the file on your device, you can use one of the following tools: * Xcode via the "Devices and Simulators" window * [`ios-deploy`](https://github.com/ios-control/ios-deploy) command line tool * [`Apple Configurator 2`](https://apps.apple.com/us/app/apple-configurator-2/) from the macOS App Store * iTunes You can also use the `xcrun simctl` command line tool to work with the iOS simulators available via Xcode: ``` # show a list of available devices xcrun simctl list # boot an iPhone X simulator xcrun simctl boot "iPhone X" # install your.app to a booted simulator xcrun simctl install booted your.app # launch the simulator open /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app ``` ## Apple Privacy Manifest The privacy manifest is a property list that records the types of data collected by your app or third-party SDK, and the required reasons APIs your app or third-party SDK uses. For each type of data your app or third-party SDK collects and category of required reasons API it uses, the app or third-party SDK needs to record the reasons in its bundled privacy manifest file. Defold provides a default privacy manifest through the Privacy Manifest field in the *game.project* file. When creating an application bundle the privacy manifest will be merged with any privacy manifests in the project dependencies and included in the application bundle. Read more about privacy manifests in the [official documentation from Apple](https://developer.apple.com/documentation/bundleresources/privacy_manifest_files?language=objc). ## Export Compliance information When you submit your game to the App Store you will be asked to provide Export Compliance information with regard to the use of encryption in your game. [Apple explains why this is required](https://developer.apple.com/documentation/security/complying_with_encryption_export_regulations): "When you submit your app to TestFlight or the App Store, you upload your app to a server in the United States. If you distribute your app outside the U.S. or Canada, your app is subject to U.S. export laws, regardless of where your legal entity is based. If your app uses, accesses, contains, implements, or incorporates encryption, this is considered an export of encryption software, which means your app is subject to U.S. export compliance requirements, as well as the import compliance requirements of the countries where you distribute your app." The Defold game engine uses encryption for the following purposes: * Making calls over secure channels (i.e. HTTPS and SSL) * Copyright protection of Lua code (to prevent duplication) These uses of encryption in the Defold engine are exempt from export compliance document requirements under United States and European Union law. Most Defold projects will remain exempt, but the addition of other cryptographic methods may change this status. It is your responsibility to ensure that your project meets the requirements of these laws and the App Store's rules. See Apple's [Export Compliance Overview](https://help.apple.com/app-store-connect/#/dev88f5c7bf9) for more information. If you believe your project is exempt, set the [`ITSAppUsesNonExemptEncryption`](https://developer.apple.com/documentation/bundleresources/information-property-list/itsappusesnonexemptencryption) key to `False` in the project's `Info.plist` see [Application Manifests](#manuals:extensions-manifest-merge-tool) for more details. ## FAQ #### Q: I am unable to install my Defold game using a free Apple Developer account. A: Make sure that you are using the same bundle identifier in your Defold project as you used in the Xcode project when you generated the mobile provisioning profile. #### Q: How can I check the entitlements of a bundled application? A: From [Inspect the entitlements of a built app](https://developer.apple.com/library/archive/technotes/tn2415/_index.html#//apple_ref/doc/uid/DTS40016427-CH1-APPENTITLEMENTS): ```sh codesign -d --ent :- /path/to/the.app ``` #### Q: How can I check the entitlements of a provisioning profile A: From [Inspecting a profile's entitlements](https://developer.apple.com/library/archive/technotes/tn2415/_index.html#//apple_ref/doc/uid/DTS40016427-CH1-PROFILESENTITLEMENTS): ```sh security cms -D -i /path/to/iOSTeamProfile.mobileprovision ``` # Nintendo Switch development {#manuals:nintendo-switch} Due to Nintendo licensing restrictions access to Defold versions with support for the Nintendo Switch platform is not included in the standard version of Defold. In order to get access to versions of Defold with Nintendo Switch support you need to become an approved game developer for Nintendo Switch. ## Registering as a Nintendo Switch developer You can register as a game developer for Nintendo Switch at the [Nintendo Developer Portal](https://developer.nintendo.com/register): When you have been approved by Nintendo you will get access to the Tools and Middleware page of the Nintendo Developer Portal where you can sign up for Defold access. When you register for Defold access we will get an email from Nintendo verifying you as a registered Nintendo developer. ## Nintendo Switch access in Defold Once we have confirmed your status as an approved Nintendo Switch developer we will provide you with access to the following: * Source code access to the Nintendo Switch extension with console specific API integrations. * Source code access to the Nintendo Switch enabled version of the Defold game engine. Note that the source code access is not required to build games for Nintendo Switch, but we provide access in case you wish to make source contributions to the engine core. * [Command line tool](#manuals:bob) with support for bundling to the Nintendo Switch platform. Bundling from the Defold editor is not supported. * Forum where you are able to get Nintendo Switch specific support. ## FAQ #### Q: Do I need to install additional tools to build for consoles? A: You will be able to create application bundles from the editor and command line tools. Information about how to test on PlayStation®4, PlayStation®5 and Nintendo Switch hardware will be provided to you when you are given access to the respective platforms. #### Q: Is it still easy to use a single code base if I decide to also target consoles? A: Yes, all of the standard Defold API functions are available also for the console platforms. In addition to the standard functionality you will also have access to a couple of PlayStation®4, PlayStation®5 and Nintendo Switch specific functions, but in general the code should be able to remain exactly the same across multiple platforms. # Game development for PlayStation®4 and PlayStation®5 consoles {#manuals:sony-playstation} Due to licensing restrictions, access to Defold versions with support for development on PS4 and PS5 is not included in the standard version of Defold. In order to get access to versions of Defold with PS4 and PS5 game development support you need to be registered as a licensed PS4 and PS5 game developer respectively. ## Registering as developer for PS4 and PS5 game development You can register as a game developer for PS4™ and PS5™ game development from the [PlayStation™ Partners page](https://register.playstation.net/partnership) When you have been approved by Sony you will get access to the Playstation 5 DevNet and/or Playstation 4 DevNet. Navigate to Development > Tools & Middleware > Tools & Middleware directory > Defold. Click the ‘Confirm Status’ button. ## PS4™ and PS5™ access in Defold Once we have received confirmation of your status as a licensed developer for PS4™ and PS5™ we will provide you with access to the following: * Source code access to the PS4™ and PS5™ extension with console specific API integrations. * Source code access to the PS4™ and PS5™ enabled version of the Defold game engine will only be provided to PS5™ licensed game developers. Note that the source code access is not required to build games, but we provide access in case you wish to make source contributions to the engine core. * [Command line tool](#manuals:bob) with support for bundling to the PS4™ and PS5™ platforms. Bundling from the Defold editor is not supported. * Forum where you are able to get PS4™ and PS5™ specific support. ## FAQ #### Q: Do I need to install additional tools to build for consoles? A: You will be able to create application bundles from the editor and command line tools. Information about how to test on PlayStation®4, PlayStation®5 and Nintendo Switch hardware will be provided to you when you are given access to the respective platforms. #### Q: Is it still easy to use a single code base if I decide to also target consoles? A: Yes, all of the standard Defold API functions are available also for the console platforms. In addition to the standard functionality you will also have access to a couple of PlayStation®4, PlayStation®5 and Nintendo Switch specific functions, but in general the code should be able to remain exactly the same across multiple platforms. # Xbox support {#manuals:microsoft-xbox} Defold does not yet support Microsoft Xbox. The Defold Foundation is actively working towards becoming an Xbox Middleware provider. We encourage approved Xbox developers to reach out to their Xbox developer contact and request Defold support for Microsoft Xbox. # HTML5 development {#manuals:html5} Defold supports building games for the HTML5 platform through the regular bundling menu, as well as for other platforms. In addition, the resulting game is embedded on a regular HTML page that can be styled through a simple template system. The *game.project* file contains the HTML5 specific settings: ## Heap size Defold support for HTML5 is powered by Emscripten (See http://en.wikipedia.org/wiki/Emscripten). In short, it creates a sandbox of memory for the heap in which the application operates. By default, the engine allocates a generous amount of memory (256MB). This should be more than sufficient for the typical game. As part of your optimization process, you may choose to use a smaller value. To do this, follow these steps: 1. Set *heap_size* to a preferred value. It should be expressed in megabytes. 2. Create your HTML5 bundle (see below) ## Testing HTML5 build For testing, HTML5 build needs an HTTP server. Defold creates one for you if you choose `Project ▸ Build HTML5`. If you want to test your bundle, just upload it to your remote HTTP server or create a local server, for example, using python in the bundle folder. Python 2: ```sh python -m SimpleHTTPServer ``` Python 3: ```sh python -m http.server ``` or ```sh python3 -m http.server ``` You can't test the HTML5 bundle by opening `index.html` file in a browser. This requires HTTP server. If you see a `"wasm streaming compile failed: TypeError: Failed to execute ‘compile’ on ‘WebAssembly’: Incorrect response MIME type. Expected ‘application/wasm’."` error in the console you must make sure that your server uses the `application/wasm` MIME type for `.wasm` files. ## Creating HTML5 bundle Creating HTML5 content with Defold is simple and follows the same pattern as all other supported platforms: select `Project ▸ Bundle... ▸ HTML5 Application...` from the menu: You can chose to include both an `asm.js` and a WebAssembly (wasm) version of the Defold engine in HTML5 bundle. In most cases it is enough to chose WebAssembly since [all modern browsers support WebAssembly](https://caniuse.com/wasm). Even if you include both `asm.js` and `wasm` versions of the engine only one of them will be downloaded by the browser when launching the game. The WebAssembly version will be downloaded if the browser supports WebAssembly and the `asm.js` version will be used as a fallback in the rare case that WebAssembly is not supported. When you click on the `Create bundle` button you will be prompted to select a folder in which to create your application. After the export process completes, you will find all of the files needed to run the application. ## Known issues and limitations * Hot Reload - Hot Reload doesn't work in HTML5 builds. Defold applications must run their own miniature web server in order to receive updates from the editor, which isn't possible in a HTML5 build. * Internet Explorer 11 * Audio - Defold handles audio playback using HTML5 _WebAudio_ (see http://www.w3.org/TR/webaudio), which is not currently supported by Internet Explorer 11. Applications will fall back to a null audio implementation when using this browser. * WebGL - Microsoft has not completed work implementing the _WebGL_ API (see https://www.khronos.org/registry/webgl/specs/latest/). Therefore, it does not perform as well as other browsers. * Full screen - Full screen mode is unreliable in the browser. * Chrome * Slow debug builds - In debug builds on HTML5 we verify all WebGL graphics calls to detect errors. This is unfortunately very slow when testing on Chrome. It is possible to disable this by setting the *Engine Arguments* field of *game.project* to `--verify-graphics-calls=false`. * Gamepad support - [Refer to the Gamepad documentation](#manuals:input-gamepads) for special considerations and steps you may need to take on HTML5. ## Customizing HTML5 bundle When generating an HTML5 version of your game, Defold provides a default web page. It references style and script resources that dictate how your game is presented. Each time the application is exported, this content is created afresh. If you wish to customize any of these elements you must make modifications to your project settings. To do so, open the *game.project* in the Defold editor and scroll to the *html5* section: More information about every option is available in [project settings manual](#manuals:project-settings). You can't modify files of the default html/css template in `builtins` folder. For applying your modifications copy/paste needed file from `builtins` and set this file in *game.project*. The canvas shouldn't be styled with any border or padding. If you do, mouse input coordinates will be wrong. In *game.project* it is possible to turn-off the `Fullscreen` button and the `Made with Defold` link. Defold provides a dark and light theme for the index.html. The light theme is set by default but it is possible to change by changing `Custom CSS` file. There is also four predefined scale modes to chose from in the `Scale Mode` field. The calculations for all scale modes include current screen DPI in case if you turn on `High Dpi` option in *game.project* (`Display` section) ### Downscale Fit and Fit For the `Fit` mode canvas size will be changed to show full game canvas on the screen with original proportions. The only difference in `Downscale Fit` is changing size only if the inner size of the webpage is smaller than the original canvas of the game, but doesn't scale-up when a webpage is bigger than the original game canvas. ### Stretch For the `Stretch` mode canvas size will be changed to fully fill the inner size of the webpage. ### No Scale With `No Scale` mode the canvas size is exactly the same as you predefined in *game.project* file, `[display]` section. ## Tokens We use [Mustache template language](https://mustache.github.io/mustache.5.html) for creation of the `index.html` file. When your are building or bundling, the HTML and CSS files are passed through a compiler that is capable of replacing certain tokens with values that depend upon your project settings. These tokens are always encased in either double or triple curly braces (`{% raw %}{{TOKEN}}{% endraw %}` or `{% raw %}{{{TOKEN}}}{% endraw %}`), depending on whether character sequences should be escaped or not. This feature can be useful if you either make frequent changes to your project settings or intend for material to be reused in other projects. More information about Mustache template language is available in [manual](https://mustache.github.io/mustache.5.html). Any *game.project* can be a token. For example, if you want to use `Width` value from `Display` section: Open *game.project* as a text and check `[section_name]` and name of the field you want to use. Then you can use it as a token: `{% raw %}{{section_name.field}}{% endraw %}` or `{% raw %}{{{section_name.field}}}{% endraw %}`. For example, in HTML template in JavaScript: ```javascript function doSomething() { var x = {% raw %}{{display.width}}{% endraw %}; // ... } ``` Also, we have the following custom tokens: DEFOLD_SPLASH_IMAGE : Writes the filename of the splash image file or `false` if `html5.splash_image` in *game.project* is empty ```css {% raw %}{{#DEFOLD_SPLASH_IMAGE}}{% endraw %} background-image: url("{% raw %}{{DEFOLD_SPLASH_IMAGE}}{% endraw %}"); {% raw %}{{/DEFOLD_SPLASH_IMAGE}}{% endraw %} ``` exe-name : The project name without unacceptable symbols DEFOLD_CUSTOM_CSS_INLINE : This is the place when we inline of the CSS file specified in your *game.project* settings. ```html ``` It is important that this inline block appear before the main application script is loaded. Since it includes HTML tags, this macro should appear in triple braces `{% raw %}{{{TOKEN}}}{% endraw %}` to prevent character sequences being escaped. DEFOLD_SCALE_MODE_IS_DOWNSCALE_FIT : This token is `true` if `html5.scale_mode` is `Downscale Fit`. DEFOLD_SCALE_MODE_IS_FIT : This token is `true` if `html5.scale_mode` is `Fit`. DEFOLD_SCALE_MODE_IS_NO_SCALE : This token is `true` if `html5.scale_mode` is `No Scale`. DEFOLD_SCALE_MODE_IS_STRETCH : This token is `true` if `html5.scale_mode` is `Stretch`. DEFOLD_HEAP_SIZE : Heap size specified in *game.project* `html5.heap_size` converted to bytes. DEFOLD_ENGINE_ARGUMENTS : Engine arguments specified in *game.project* `html5.engine_arguments` separated by `,` symbol. build-timestamp : Current build timestamp in seconds. ## Extra parameters If you create your custom template, you can redefine set of parameters for the engine loader. To achieve that you need to add `` section and redefine values inside `CUSTOM_PARAMETERS`. Your custom `` should be placed after `` section with reference to `dmloader.js` but before call `EngineLoader.load` function. For example: ``` ``` `CUSTOM_PARAMETERS` may contains following fields: ``` 'archive_location_filter': Filter function that will run for each archive path. 'unsupported_webgl_callback': Function that is called if WebGL is not supported. 'engine_arguments': List of arguments (strings) that will be passed to the engine. 'custom_heap_size': Number of bytes specifying the memory heap size. 'disable_context_menu': Disables the right-click context menu on the canvas element if true. 'retry_time': Pause in seconds before retry file loading after error. 'retry_count': How many attempts we do when trying to download a file. 'can_not_download_file_callback': Function that is called if you can't download file after 'retry_count' attempts. 'resize_window_callback': Function that is called when resize/orientationchanges/focus events happened 'start_success': Function that is called just before main is called upon successful load. 'update_progress': Function that is called as progress is updated. Parameter progress is updated 0-100. ``` ## File operations in HTML5 HTML5 builds support file operations such as `sys.save()`, `sys.load()` and `io.open()` but the way these operations are handled internally is different from other platforms. When Javascript is run in a browser there is no real concept of a file system and local file access is blocked for security reasons. Instead Emscripten (and thus Defold) uses [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB), an in-browser database used to persistently store data, to create a virtual filesystem in the browser. The important difference from file system access on other platforms is that there can be a slight delay between writing to a file and the change actually being stored in the database. The browser developer console usually allows you to inspect the contents of the IndexedDB. ## Passing arguments to an HTML5 game It is sometimes necessary to provide additional arguments to a game before it or as it is started. This could for instance be a user id, session token or which level to load when the game starts. This can be achieved in a number of different ways, some of which are described here. ### Engine arguments It is possible to specify additional engine arguments when the engine is configured and loaded. These extra engine arguments can at runtime be retrieved using `sys.get_config()`. To add the key-value pairs you modify the `engine_arguments` field of the `extra_params` object that is passed to the engine when loaded in `index.html`: ``` ``` Extension manifest ```html ``` Result ```html ``` # Build server local setup {#manuals:extender-local-setup} There are two variants how to run local build server (aka 'Extender'): 1. Run local build server with preconfigured artifacts. 2. Run local build server with locally built artifacts. ## How to run local Extender with preconfigured artifacts Before you can run a local cloud builder you need to install the following software: * [Docker](https://www.docker.com/) - Docker is a set of platform as a service products that use OS-level virtualization to deliver software in packages called containers. To run the cloud builders on your local development machine you need to install [Docker Desktop](https://www.docker.com/products/docker-desktop/) * Google Cloud CLI - The Google Cloud CLI is a set of tools to create and manage Google Cloud resources. The tools can be [installed directly from Google](https://cloud.google.com/sdk/docs/install) or from a package manager such as Brew, Chocolatey or Snap. * You also need a Google account to download the containers with the platform specific build servers. Once you have the above mentioned software installed follow these steps to install and run the Defold cloud builders: **Note for Windows users**: use git bash terminal for executing commands below. 1. __Authorize to Google Cloud and create Application default credentials__ - You need to have a Google account when downloading the Docker container images so that we can monitor and ensure fair use of the public container registry and temporarily suspend accounts which download images excessively. ```sh gcloud auth login ``` 2. __Configure Docker to use Artifact registries__ - Docker needs to be configured to use `gcloud` as a credential helper when downloading container images from the public container registry at `europe-west1-docker.pkg.dev`. ```sh gcloud auth configure-docker europe-west1-docker.pkg.dev ``` 3. __Verify that Docker and Google Cloud are configured correctly__ - Verify that Docker and Google Cloud are set up successfully by pulling the base image used by all of the build server container images. Make sure that Docker Desktop is running before running the command below: ```sh docker pull --platform linux/amd64 europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-base-env:latest ``` 4. __Clone Extender repository__ - With Docker and Google Cloud correctly set up we are almost ready to start the servers. Before we can start the server we need to clone the Git repository containing the build server: ```sh git clone https://github.com/defold/extender.git cd extender ``` 5. __Download prebuilt jars__ - Next step is to download the prebuilt server (`extender.jar`) and manifest merge tool (`manifestmergetool.jar`): ```sh TMP_DIR=$(pwd)/server/_tmp APPLICATION_DIR=$(pwd)/server/app # set necessary version of Extender and Manifest merge tool # versions can be found at Github release page https://github.com/defold/extender/releases # or you can pull latest version (see code sample below) EXTENDER_VERSION=2.6.5 MANIFESTMERGETOOL_VERSION=1.3.0 echo "Download prebuild jars to ${APPLICATION_DIR}" rm -rf ${TMP_DIR} mkdir -p ${TMP_DIR} rm -rf ${APPLICATION_DIR} mkdir -p ${APPLICATION_DIR} gcloud artifacts files download \ --project=extender-426409 \ --location=europe-west1 \ --repository=extender-maven \ --destination=${TMP_DIR} \ com/defold/extender/server/${EXTENDER_VERSION}/server-${EXTENDER_VERSION}.jar gcloud artifacts files download \ --project=extender-426409 \ --location=europe-west1 \ --repository=extender-maven \ --destination=${TMP_DIR} \ com/defold/extender/manifestmergetool/${MANIFESTMERGETOOL_VERSION}/manifestmergetool-${MANIFESTMERGETOOL_VERSION}.jar cp ${TMP_DIR}/$(ls ${TMP_DIR} | grep server-${EXTENDER_VERSION}.jar) ${APPLICATION_DIR}/extender.jar cp ${TMP_DIR}/$(ls ${TMP_DIR} | grep manifestmergetool-${MANIFESTMERGETOOL_VERSION}.jar) ${APPLICATION_DIR}/manifestmergetool.jar ``` 6. __Start the server__ - We can now start the server by running the docker compose main command: ```sh docker compose -p extender -f server/docker/docker-compose.yml --profile up ``` where *profile* can be: * **all** - runs remote instances for every platform * **android** - runs frontend instance + remote instances to build Android version * **web** - runs frontend instance + remote instances to build Web version * **linux** - runs frontend instance + remote instances to build Linux version * **windows** - runs frontend instance + remote instances to build Windows version * **consoles** - runs frontend instance + remote instances to build Nintendo Switch/PS4/PS5 versions * **nintendo** - runs frontend instance + remote instances to build Nintendo Switch version * **playstation** - runs frontend instance + remote instances to build PS4/PS5 versions * **metrics** - runs VictoriaMetrics + Grafana as metrics backend and tool for visualization For more information about `docker compose` arguments see https://docs.docker.com/reference/cli/docker/compose/. When docker compose is up you can use **http://localhost:9000** as Build server address in Editor's preference or as `--build-server` value if you use Bob to build the project. Several profiles can be passed to command line. For example: ```sh docker compose -p extender -f server/docker/docker-compose.yml --profile android --profile web --profile windows up ``` Example above runs frontend, Android, Web, Windows instances. To stop services - Press Ctrl+C if docker compose runs in non-detached mode, or ```sh docker compose -p extender down ``` if docker compose was run in detached mode (e.g. '-d' flag was passed to `docker compose up` command). If you want to pull latest versions of jars you can use following command to determine latest version ```sh EXTENDER_VERSION=$(gcloud artifacts versions list \ --project=extender-426409 \ --location=europe-west1 \ --repository=extender-maven \ --package="com.defold.extender:server" \ --sort-by="~createTime" \ --limit=1 \ --format="value(name)") MANIFESTMERGETOOL_VERSION=$(gcloud artifacts versions list \ --project=extender-426409 \ --location=europe-west1 \ --repository=extender-maven \ --package="com.defold.extender:manifestmergetool" \ --sort-by="~createTime" \ --limit=1 \ --format="value(name)") ``` ### What about macOS and iOS? The macOS and iOS builds are done on real Apple hardware using a build server running in stand-alone mode without Docker. Instead XCode, Java and other required tools are installed directly on the machine and the build server is running as a normal Java process. You can learn how to set this up in the [build server documentation on GitHub](https://github.com/defold/extender?tab=readme-ov-file#running-as-a-stand-alone-server-on-macos). ## How to run local Extender with locally built artifacts Please follow the [instructions in the Extender repository on GitHub](https://github.com/defold/extender) to manually build and run a local build server. # Available Docker images {#manuals:extender-docker-images} Below is the list of all available Docker images in public Registry. The images can be used to run Extender in environment with old SDKs that are no longer supported. |SDK |Image tag |Platform name (in Extender's config) |Defold version that used image | |------------------|---------------------------------------------------------------------------------------------------------|-------------------------------------|-------------------------------| |Linux latest |`europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-linux-env:latest` |`linux-latest` |All Defold versions | |Android NDK25 |`europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-android-ndk25-env:latest` |`android-ndk25` |Since 1.4.3 | |Emscripten 2.0.11 |`europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-emsdk-2011-env:latest` |`emsdk-2011` |Until 1.7.0 | |Emscripten 3.1.55 |`europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-emsdk-3155-env:latest` |`emsdk-3155` |[1.8.0-1.9.3] | |Emscripten 3.1.65 |`europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-emsdk-3165-env:latest` |`emsdk-3165` |Since 1.9.4 | |Winsdk 2019 |`europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-winsdk-2019-env:latest` |`winsdk-2019` |Until 1.6.1 | |Winsdk 2022 |`europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-winsdk-2022-env:latest` |`winsdk-2022` |Since 1.6.2 | # How to use old Docker images To use old environment you should go through following steps: 1. Modify `docker-compose.yml` from Extender's repository [link](https://github.com/defold/extender/blob/dev/server/docker/docker-compose.yml). Need to add one more definition of service with necessary Docker image. For example, if we want to use Docker image that contains Emscripten 2.0.11 we need to add following service definition: ```yml emscripten_2011-dev: image: europe-west1-docker.pkg.dev/extender-426409/extender-public-registry/extender-emsdk-2011-env:latest extends: file: common-services.yml service: remote_builder profiles: - all - web networks: default: aliases: - emsdk-2011 ``` Important fields are: * **profiles** - list of profiles that triggers service start. Profile names passed via `--profile ` argument to `docker compose` command. * **networks** - list of networks that should used by Docker container. For running Extender used network with name `default`. Important to set service network aliases (it will be used in later Extender's configuration). 2. Add definition of remote builder in [`application-local-dev-app.yml`](https://github.com/defold/extender/blob/dev/server/configs/application-local-dev-app.yml) in `extender.remote-builder.platforms` section. In our example it will looks like: ```yml emsdk-2011: url: http://emsdk-2011:9000 instanceId: emsdk-2011 ``` Url should be in following format: `http://:9000`, where `service_network_alias` - network alias from step 1. 9000 - standard port for Extender (can be different if you are using custom Extender configuration). 3. Run local Extender as it described in [How to run local Extender with preconfigured artifacts](#manuals:extender-local-setup#how-to-run-local-extender-with-preconfigured-artifacts). # Ddf {#apis:engine-ddf-src-dmsdk-ddf-ddf-h} **Namespace:** `dmDDF` **Language:** C++ **Type:** Defold C++ **File:** `ddf.h` **Source:** `engine/ddf/src/dmsdk/ddf/ddf.h` **Include:** `dmsdk/ddf/ddf.h` DDF (Defold Data Format) API documentation ## API ### Descriptor *Type:* TYPEDEF Opaque pointer that holds info about a message type. ### FreeMessage *Type:* FUNCTION Free message **Parameters** - `message` (void*) - The message ### GetDescriptorFromHash *Type:* FUNCTION Get Descriptor from hash name **Parameters** - `hash` (dmhash_t) - hash of type name **Returns** - `descriptor` (dmDDF::Descriptor*) - 0 if not found ### LoadMessage *Type:* FUNCTION Load/decode a DDF message from buffer **Parameters** - `buffer` (const void*) - Input buffer - `buffer_size` (uint32_t) - Input buffer size in bytes - `desc` (dmDDF::Descriptor*) - DDF descriptor - `message` (void**) - (out) Destination pointer to message **Returns** - `RESULT_OK` - on success ### LoadMessage *Type:* FUNCTION Load/decode a DDF message from buffer **Parameters** - `buffer` (const void*) - Input buffer - `buffer_size` (uint32_t) - Input buffer size in bytes - `desc` (dmDDF::Descriptor*) - DDF descriptor - `message` (void**) - (out) Destination pointer to message - `options` (uint32_t) - options, eg dmDDF::OPTION_OFFSET_POINTERS - `size` (uint32_t*) - (out) loaded message size **Returns** - `RESULT_OK` - on success ### LoadMessage *Type:* FUNCTION Load/decode a DDF message from buffer. Template variant **Template Parameters** - `T` **Parameters** - `buffer` (const void*) - Input buffer - `buffer_size` (uint32_t) - Input buffer size in bytes - `message` (T**) - (out) Destination pointer to message **Returns** - `RESULT_OK` - on success ### LoadMessageFromFile *Type:* FUNCTION Load/decode a DDF message from file **Parameters** - `file_name` (const char*) - File name - `desc` (dmDDF::Descriptor*) - DDF descriptor - `message` (void**) - (out) Destination pointer to message **Returns** - `RESULT_OK` - on success ### OPTION_OFFSET_POINTERS *Type:* CONSTANT Store pointers as offset from base address. Needed when serializing entire messages (copy). Value (1 << 0) ### ResolvePointers *Type:* FUNCTION If the message was loaded with the flag dmDDF::OPTION_OFFSET_POINTERS, all pointers have their offset stored. This function resolves those offsets into actual pointers **Parameters** - `desc` (dmDDF::Descriptor*) - DDF descriptor - `message` (void*) - (int/out) The message to patch pointers in **Returns** - `RESULT_OK` - on success ### Result *Type:* ENUM Result enumeration. **Members** - `dmDDF::RESULT_OK` - = 0, - `dmDDF::RESULT_FIELDTYPE_MISMATCH` - = 1, - `dmDDF::RESULT_WIRE_FORMAT_ERROR` - = 2, - `dmDDF::RESULT_IO_ERROR` - = 3, - `dmDDF::RESULT_VERSION_MISMATCH` - = 4, - `dmDDF::RESULT_MISSING_REQUIRED` - = 5, - `dmDDF::RESULT_INTERNAL_ERROR` - = 1000, ### SaveMessageToArray *Type:* FUNCTION Save message to array **Parameters** - `message` (const void*) - Message - `desc` (dmDDF::Descriptor*) - DDF descriptor - `buffer` (dmArray&) - Buffer to save to **Returns** - `RESULT_OK` - on success # Android {#apis:engine-dlib-src-dmsdk-dlib-android-h} **Namespace:** `dmAndroid` **Language:** C++ **Type:** Defold C++ **File:** `android.h` **Source:** `engine/dlib/src/dmsdk/dlib/android.h` **Include:** `dmsdk/dlib/android.h` Android utility functions ## API ### Detach *Type:* FUNCTION Detaches the jni environment **Returns** - `ok` (bool) - true if there was no java exceptions. False if there was an exception. ### GetActivity *Type:* FUNCTION Gets the app native activity **Returns** - `activity` (ANativeActivity*) - the app native activity ### GetEnv *Type:* FUNCTION Gets the JNI environment **Returns** - `env` (JNIENV*) - the attached environment ### IsAttached *Type:* FUNCTION Is the environment attached and valid? **Returns** - `isattached` (bool) - true if the environment is valid **Examples** ``` Result SomeFunc() { ThreadAttacher thread; JNIEnv* env = thread.GetEnv(); if (!env) return RESULT_ATTACH_FAILED; ... calls using jni return thread.Detach() ? RESULT_OK : RESULT_JNI_CALLS_FAILED; } ``` ### LoadClass *Type:* FUNCTION Load a class **Parameters** - `env` (JNIEnv*) - `class_name` (const char*) **Returns** - `class` (jclass) - the activity class loader ### LoadClass *Type:* FUNCTION Load a class **Parameters** - `env` (JNIEnv*) - `activity` (jobject) - `class_name` (const char*) **Returns** - `class` (jclass) - the activity class loader ### OnActivityCreate *Type:* TYPEDEF onCreate callback function type. Used with RegisterOnActivityCreateListener() and UnregisterOnActivityCreateListener() **Parameters** - `env` (JNIEnv*) - `activity` (jobject) ### OnActivityResult *Type:* TYPEDEF Activity result callback function type. Monitors events from the main activity. Used with RegisterOnActivityResultListener() and UnregisterOnActivityResultListener() **Parameters** - `env` (JNIEnv*) - `activity` (jobject) - `request_code` (int32_t) - `result_code` (int32_t) - `result` (void*) ### RegisterOnActivityCreateListener *Type:* FUNCTION Registers an onCreate callback. Multiple listeners are allowed. **Notes** - [icon:android] Only available on Android **Parameters** - `listener` (dmAndroid::OnActivityCreate) ### RegisterOnActivityResultListener *Type:* FUNCTION Registers an activity result callback. Multiple listeners are allowed. **Notes** - [icon:android] Only available on Android **Parameters** - `listener` (dmAndroid::OnActivityResult) ### ThreadAttacher *Type:* CLASS Struct attaching the JNI environment. ### ThreadAttacher *Type:* FUNCTION constructor **Examples** ``` { ThreadAttacher thread; SomeFunction( thread.GetEnv() ); // Automatically detaches } ``` ``` { ThreadAttacher thread; JNIEnv* env = thread.GetEnv(); if (!env) return; ... } ``` ### UnregisterOnActivityCreateListener *Type:* FUNCTION Unregisters an onCreate callback **Notes** - [icon:android] Only available on Android **Parameters** - `listener` (dmAndroid::OnActivityCreate) ### UnregisterOnActivityResultListener *Type:* FUNCTION Unregisters an activity result callback **Notes** - [icon:android] Only available on Android **Parameters** - `listener` (dmAndroid::OnActivityResult) # Array {#apis:engine-dlib-src-dmsdk-dlib-array-h} **Namespace:** `Array` **Language:** C++ **Type:** Defold C++ **File:** `array.h` **Source:** `engine/dlib/src/dmsdk/dlib/array.h` **Include:** `dmsdk/dlib/array.h` Templatized array with bounds checking. The backing storage is either auto-allocated (dynamically allocated) or user-allocated (supplied by user). With exception of changing the size and capacity, all operations are guaranteed to be O(1). ```cpp dmArray a; a.SetCapacity(1); a.Push(1); int b = a[0]; ``` ## API ### Back *Type:* FUNCTION Last element of the array **Returns** - `reference` (T&) - reference to the last element ### Back *Type:* FUNCTION Last element of the array (const) **Returns** - `reference` (const T&) - const-reference to the last element ### Begin *Type:* FUNCTION Pointer to the start of the backing storage **Returns** - `pointer` (T*) - pointer to start of memory ### Begin *Type:* FUNCTION Pointer to the start of the backing storage **Returns** - `pointer` (const T*) - pointer to start of memory ### Capacity *Type:* FUNCTION Capacity is currently allocated storage. **Returns** - `number` (uint32_t) - array capacity ### DM_ARRAY_SIZE *Type:* MACRO get number of elements in C array **Parameters** - `A` (T) - C array to count **Returns** - `Number` - of elements ### dmArray *Type:* CLASS The backing storage is either auto-allocated (dynamically allocated) or user-allocated (supplied by user). With exception of changing the size and capacity, all operations are guaranteed to be O(1). **Template Parameters** - `T` - Contained type, must obey memcpy semantics ### dmArray *Type:* FUNCTION constructor. empty auto-allocated memory **Examples** ``` dmArray a; a.Push(1); ``` ### dmArray *Type:* FUNCTION user-allocated array with initial size and capacity **Parameters** - `user_array` (T*) - User-allocated array to be used as storage. - `size` (uint32_t) - Initial size - `capacity` (uint32_t) - Initial capacity ### dmArray *Type:* FUNCTION user-allocated array with initial size and capacity **Parameters** - `user_array` (T*) - User-allocated array to be used as storage. - `size` (uint32_t) - Initial size - `capacity` (uint32_t) - Initial capacity - `user_allocated` (bool) - If false, the ownership is transferred to the dmArray ### Empty *Type:* FUNCTION Check if the array is empty. The array is empty when the size is zero. **Returns** - `boolean` (bool) - true if the array is empty ### End *Type:* FUNCTION Pointer to the end of the backing storage The end is essentially outside of the used storage. **Returns** - `pointer` (T*) - pointer to end of memory ### End *Type:* FUNCTION Pointer to the end of the backing storage The end is essentially outside of the used storage. **Returns** - `pointer` (const T*) - pointer to end of memory ### EraseSwap *Type:* FUNCTION Remove the element at the specified index. The removed element is replaced by the element at the end (if any), thus potentially altering the order. While operation changes the array size, it is guaranteed to be O(1). **Parameters** - `index` (uint32_t) - index of the element to remove **Returns** - `reference` (T&) - reference to the new element at index ### EraseSwapRef *Type:* FUNCTION Remove the element by reference The removed element is replaced by the element at the end (if any), thus potentially altering the order. While operation changes the array size, it is guaranteed to be O(1). **Parameters** - `element` (T&) - reference to the element to remove. **Returns** - `reference` (T&) - reference to the new referenced element ### Front *Type:* FUNCTION First element of the array **Returns** - `reference` (T&) - reference to the first element ### Front *Type:* FUNCTION First element of the array (const) **Returns** - `reference` (const T&) - const-reference to the first element ### Full *Type:* FUNCTION Check if the array is full. The array is full when the size is equal to the capacity. **Returns** - `boolean` (bool) - true if the array is full ### Map *Type:* FUNCTION map a function on all values **Parameters** - `fn` (void*) - function that will be called for each element - `ctx` (void*) - user defined context that will be passed in with each callback ### OffsetCapacity *Type:* FUNCTION Relative change of capacity Equivalent to SetCapacity(Capacity() + offset). Only allowed for auto-allocated arrays and will result in a new dynamic allocation followed by memcpy of the elements. **Parameters** - `offset` (uint32_t) - relative amount of elements to change the capacity ### operator[] *Type:* FUNCTION Retrieve an element by index **Parameters** - `index` (uint32_t) - array index **Returns** - `reference` (T&) - reference to the element at the specified index ### operator[] *Type:* FUNCTION Retrieve an element by index (const) **Parameters** - `index` (uint32_t) - array index **Returns** - `reference` (const T&) - const-reference to the element at the specified index ### Pop *Type:* FUNCTION Remove the last element of the array Only allowed when the size is larger than zero. ### Push *Type:* FUNCTION Add an element to the end of the array Only allowed when the capacity is larger than size. **Parameters** - `element` (const T&) - element element to add ### PushArray *Type:* FUNCTION Add an array of elements to the end of the array Only allowed when the capacity is larger than size + count **Parameters** - `array` (const T*) - array of elements to add - `count` (uint32_t) - amount of elements in the array ### Remaining *Type:* FUNCTION Amount of additional elements that can be stored **Returns** - `number` (uint32_t) - amount of additional elements that can be stored ### SetCapacity *Type:* FUNCTION Set the capacity of the array. If the size is less than the capacity, the array is truncated. If it is larger, the array is extended. Only allowed for auto-allocated arrays and will result in a new dynamic allocation followed by memcpy of the elements. **Parameters** - `capacity` (uint32_t) - capacity of the array ### SetSize *Type:* FUNCTION Set size of the array **Parameters** - `size` (uint32_t) - size of the array, must be less or equal to the capacity ### Size *Type:* FUNCTION Size of the array in elements **Returns** - `number` (uint32_t) - array size ### Swap *Type:* FUNCTION Swap the content of two arrays **Parameters** - `rhs` (dmArray&) - reference to array to swap content with ### ~dmArray *Type:* FUNCTION Only frees memory when auto-allocated. # Buffer {#apis:engine-dlib-src-dmsdk-dlib-buffer-h} **Namespace:** `dmBuffer` **Language:** C++ **Type:** Defold C++ **File:** `buffer.h` **Source:** `engine/dlib/src/dmsdk/dlib/buffer.h` **Include:** `dmsdk/dlib/buffer.h` Buffer API for data buffers as the main way to communicate between systems. ## API ### dmBuffer::Copy *Type:* FUNCTION Copies the data from one buffer to another buffer. The stream declaration needs to be the same in both buffers. **Parameters** - `dst_buffer_handle` (dmBuffer::HBuffer*) - Pointer to HBuffer from where to copy buffer data. - `src_buffer_handle` (dmBuffer::HBuffer*) - Pointer to HBuffer where to copy the buffer data. **Returns** - `result` (dmBuffer::Result) - BUFFER_OK if buffer was copied successfully **Examples** ``` dmBuffer::Result r = dmBuffer::Copy(buffer_a, buffer_b); if (r == dmBuffer::RESULT_OK) { // success } else { // handle error } ``` ### dmBuffer::Create *Type:* FUNCTION Creates a new HBuffer with a number of different streams. **Parameters** - `count` (uint32_t) - The number of "structs" the buffer should hold (e.g. vertex count) - `streams_decl` (const dmBuffer::StreamDeclaration*) - Array of stream declarations - `streams_decl_count` (uint8_t) - Number of stream declarations inside the decl array (max 256) - `out_buffer` (dmBuffer::HBuffer*) - Pointer to HBuffer where to store the newly allocated buffer **Returns** - `result` (dmBuffer::Result) - BUFFER_OK if buffer was allocated successfully **Examples** ``` const dmBuffer::StreamDeclaration streams_decl[] = { {dmHashString64("position"), dmBuffer::VALUE_TYPE_FLOAT32, 3}, {dmHashString64("texcoord0"), dmBuffer::VALUE_TYPE_UINT16, 2}, {dmHashString64("color"), dmBuffer::VALUE_TYPE_UINT8, 4}, }; dmBuffer::HBuffer buffer = 0x0; dmBuffer::Result r = dmBuffer::Create(1024, streams_decl, 3, &buffer); if (r == dmBuffer::RESULT_OK) { // success } else { // handle error } ``` ### dmBuffer::Destroy *Type:* FUNCTION Destroys a HBuffer and it's streams. **Parameters** - `buffer` (dmBuffer::HBuffer) - Buffer handle to the buffer to free **Examples** ``` const dmBuffer::StreamDeclaration streams_decl[] = { {dmHashString64("position"), dmBuffer::VALUE_TYPE_FLOAT32, 3}, }; dmBuffer::HBuffer buffer = 0x0; dmBuffer::Result r = dmBuffer::Create(4, streams_decl, 1, &buffer); if (r == dmBuffer::RESULT_OK) { dmBuffer::Destroy(buffer); } else { // handle error } ``` ### dmBuffer::GetBytes *Type:* FUNCTION Gets the buffer as a byte array. If the buffer is interleaved (default), a pointer to the whole memory is returned. **Parameters** - `buffer` (dmBuffer::HBuffer) - buffer handle. - `out_bytes` (void**) - Pointer to void* where to store the bytes - `out_size` (uint32_t*) - Pointer to uint32_t where to store the array size **Returns** - `result` (dmBuffer::Result) - BUFFER_OK if the buffer was successfully accessed **Examples** ``` uint8_t* bytes = 0x0; uint32_t size = 0; dmBuffer::Result r = dmBuffer::GetBytes(buffer, (void**)&bytes, &size); if (r == dmBuffer::RESULT_OK) { for (int i = 0; i < size; ++i) { stream[i] = (uint8_t)(i & 0xFF); } } else { // handle error } ``` ### dmBuffer::GetContentVersion *Type:* FUNCTION Gets the current update number **Parameters** - `type` (dmBuffer::HBuffer) - The value type - `version` (uint32_t*) - The current version number **Returns** - `result` (dmBuffer::Result) - Returns BUFFER_OK if all went ok ### dmBuffer::GetCount *Type:* FUNCTION Get (struct) count for a buffer. **Parameters** - `buffer` (dmBuffer::HBuffer) - buffer handle. - `count` (uint32_t*) - Pointer to uint32_t where to store the element count **Returns** - `result` (dmBuffer::Result) - BUFFER_OK if the element count was successfully accessed **Examples** ``` uint32_t count = 0; dmBuffer::Result r = dmBuffer::GetCount(buffer, &count); if (r == dmBuffer::RESULT_OK) { printf("buffer %p has %d number of elements", buffer, count); } else { // handle error } ``` ### dmBuffer::GetMetaData *Type:* FUNCTION Retrieve metadata entry information **Parameters** - `hbuffer` (dmBuffer::HBuffer) - A buffer handle - `name_hash` (dmhash_t) - The entry name as a hash - `data` (void**) - Gets the internal address of metadata values - `count` (uint32_t) - Gets the number of metadata values stored - `type` (dmBuffer::ValueType) - Gets the type of values of the metadata ### dmBuffer::GetResultString *Type:* FUNCTION Converts result to string **Parameters** - `result` (dmBuffer::Result) - The result **Returns** - `result` (const char*) - The result as a string ### dmBuffer::GetSizeForValueType *Type:* FUNCTION Gets the size of a value type **Parameters** - `type` (dmBuffer::ValueType) - The value type **Returns** - `size` (uint32_t) - The size in bytes ### dmBuffer::GetStream *Type:* FUNCTION Get a stream from a buffer. Output stream is 16 byte aligned. **Parameters** - `buffer` (dmBuffer::HBuffer) - buffer handle. - `stream_name` (dmhash_t) - Hash of stream name to get - `stream` (void**) - Where to store the stream - `count` (uint32_t*) - Where to store the count (e.g. vertex count). May be null. - `components` (uint32_t*) - Where to store the number of components (e.g. 3 for a Vector3). May be null. - `stride` (uint32_t*) - Where to store the (struct) stride. The stride can be added to the value pointer. May be null. E.g. for a float array, the stride is (sizeof(Struct) / sizeof(float)) **Returns** - `result` (dmBuffer::Result) - BUFFER_OK if the stream was successfully accessed **Examples** ``` float* positions = 0x0; uint32_t size = 0; uint32_t components = 0; uint32_t stride = 0; dmBuffer::Result r = dmBuffer::GetStream(buffer, dmHashString64("position"), (void**)&positions, &count, &components, &stride); if (r == dmBuffer::RESULT_OK) { for (int i = 0; i < count; ++i) { for (int c = 0; c < components; ++c) { positions[c] *= 1.1f; } positions += stride; } } else { // handle error } ``` ### dmBuffer::GetStreamType *Type:* FUNCTION Gets the stream type **Parameters** - `buffer` (dmBuffer::HBuffer) - Pointer to a buffer. - `stream_name` (dmhash_t) - Hash of stream name to get - `type` (dmBuffer::ValueType*) - The value type - `components` (uint32_t*) - The number of values (E.g. 3 for a Vector3) **Returns** - `result` (dmBuffer::Result) - Returns BUFFER_OK if all went ok ### dmBuffer::GetValueTypeString *Type:* FUNCTION Converts a value type to string **Parameters** - `result` (dmBuffer::ValueType) - The value type **Returns** - `result` (const char*) - The value type as a string ### dmBuffer::HBuffer *Type:* TYPEDEF ``` typedef uint32_t HBuffer; ``` ### dmBuffer::IsBufferValid *Type:* FUNCTION Checks if a handle is still valid **Parameters** - `buffer` (dmBuffer::HBuffer) - The buffer **Returns** - `result` (bool) - True if the handle is valid ### dmBuffer::SetMetaData *Type:* FUNCTION Create or update a new metadata entry with a number of values of a specific type. It will allocate space to store these values. **Parameters** - `hbuffer` (dmBuffer::HBuffer) - A buffer handle - `name_hash` (dmhash_t) - The entry name as a hash - `data` (void*) - A pointer to an array of the values - `count` (uint32_t) - Number of values in the array - `type` (dmBuffer::ValueType) - The type of the values **Returns** - `result` (dmBuffer::Result) - RESULT_OK if the metadata entry was successfully stored ### dmBuffer::StreamDeclaration *Type:* STRUCT Buffer stream declaration structure **Members** - `m_Name` (dmhash_t) - Hash of stream name - `m_Type` (dmBuffer::ValueType) - Stream ValueType type - `m_Count` (uint8_t) - Component count of stream type. E.g. 3 for a Vector3 - `m_Flags` (uint32_t) - Flags for a stream. - `m_Reserved` (uint32_t) - Reserved for future use. **Examples** Declare a typical position stream: ``` const dmBuffer::StreamDeclaration streams_decl[] = { {dmHashString64("position"), dmBuffer::VALUE_TYPE_FLOAT32, 3} }; ``` ### dmBuffer::UpdateContentVersion *Type:* FUNCTION Used to know if a buffer has been updated. **Parameters** - `type` (dmBuffer::HBuffer) - The value type **Returns** - `result` (dmBuffer::Result) - Returns BUFFER_OK if all went ok ### dmBuffer::ValidateBuffer *Type:* FUNCTION Validate a buffer and it's streams. **Parameters** - `buffer` (dmBuffer::HBuffer) - Buffer handle to the buffer to validate **Examples** ``` // Pass buffer to third party library that does operations on the buffer or streams. ThirdPartyLib::PerformOperation(buffer); r = dmBuffer::ValidateBuffer(buffer); if (r == dmBuffer::RESULT_OK) { // buffer and streams are valid } else { // the third party lib made the buffer invalid } ``` ### Result *Type:* ENUM Result enumeration. **Members** - `dmBuffer::RESULT_OK` - `dmBuffer::RESULT_GUARD_INVALID` - `dmBuffer::RESULT_ALLOCATION_ERROR` - `dmBuffer::RESULT_BUFFER_INVALID` - `dmBuffer::RESULT_BUFFER_SIZE_ERROR` - `dmBuffer::RESULT_STREAM_SIZE_ERROR` - `dmBuffer::RESULT_STREAM_MISSING` - `dmBuffer::RESULT_STREAM_TYPE_MISMATCH` - `dmBuffer::RESULT_STREAM_COUNT_MISMATCH` - `dmBuffer::RESULT_METADATA_INVALID` - `dmBuffer::RESULT_METADATA_MISSING` ### ValueType *Type:* ENUM ValueType enumeration. **Members** - `dmBuffer::VALUE_TYPE_UINT8` - `dmBuffer::VALUE_TYPE_UINT16` - `dmBuffer::VALUE_TYPE_UINT32` - `dmBuffer::VALUE_TYPE_UINT64` - `dmBuffer::VALUE_TYPE_INT8` - `dmBuffer::VALUE_TYPE_INT16` - `dmBuffer::VALUE_TYPE_INT32` - `dmBuffer::VALUE_TYPE_INT64` - `dmBuffer::VALUE_TYPE_FLOAT32` - `dmBuffer::MAX_VALUE_TYPE_COUNT` # Condition Variable {#apis:engine-dlib-src-dmsdk-dlib-condition_variable-h} **Namespace:** `dmConditionVariable` **Language:** C++ **Type:** Defold C++ **File:** `condition_variable.h` **Source:** `engine/dlib/src/dmsdk/dlib/condition_variable.h` **Include:** `dmsdk/dlib/condition_variable.h` API for platform independent mutex synchronization primitive. ## API ### dmConditionVariable::Broadcast *Type:* FUNCTION Broadcast condition variable, effectively unblocks all of the waiting threads blocked by the condition variable. **Parameters** - `condition` (dmConditionVariable::HConditionVariable) - ConditionVariable handle. ### dmConditionVariable::Delete *Type:* FUNCTION Deletes a HConditionVariable. **Parameters** - `mutex` (dmConditionVariable::HConditionVariable) - ConditionVariable handle to delete. ### dmConditionVariable::HConditionVariable *Type:* TYPEDEF ``` typedef struct ConditionVariable* HConditionVariable; ``` ### dmConditionVariable::New *Type:* FUNCTION Create a new HConditionVariable **Returns** - `condition_variable` (dmConditionVariable::HConditionVariable) - A new ConditionVariable handle. ### dmConditionVariable::Signal *Type:* FUNCTION Signal condition variable, effectively unblocks at least one of the waiting threads blocked by the condition variable. **Parameters** - `condition` (dmConditionVariable::HConditionVariable) - ConditionVariable handle. ### dmConditionVariable::Wait *Type:* FUNCTION Wait for condition variable. This is a blocking function, and should be called with the mutex being locked. **Parameters** - `condition` (dmConditionVariable::HConditionVariable) - ConditionVariable handle. - `mutex` (dmMutex::HMutex) - Mutex handle. # ConfigFile {#apis:engine-dlib-src-dmsdk-dlib-configfile_gen-hpp} **Namespace:** `dmConfigFile` **Language:** C++ **Type:** Defold C++ **File:** `configfile_gen.hpp` **Source:** `engine/dlib/src/dmsdk/dlib/configfile_gen.hpp` **Include:** `dmsdk/dlib/configfile_gen.hpp` Configuration file access functions. The configuration file is compiled version of the [file:game.project] file. ## API ### ConfigFileExtensionDescBufferSize *Type:* FUNCTION It defines the minimum size of the description blob being registered. ### ConfigFileGetFloat *Type:* FUNCTION Get config value as float, returns default if the key isn't found **Parameters** - `config` (HConfigFile) - Config file handle - `key` (const char*) - Key in format section.key (.key for no section) - `default_value` (int32_t) - Default value to return if key isn't found **Returns** - `value` (int32_t) - found value or default value **Examples** ``` static ExtensionResult AppInitialize(ExtensionAppParams* params) { float gravity = ConfigFileGetFloat(params->m_ConfigFile, "physics.gravity_y", -9.8f); } ``````cpp static dmExtension::Result AppInitialize(dmExtension::AppParams* params) { float gravity = dmConfigFile::GetFloat(params->m_ConfigFile, "physics.gravity_y", -9.8f); } ``` ### ConfigFileGetInt *Type:* FUNCTION Get config value as integer, returns default if the key isn't found **Parameters** - `config` (HConfigFile) - Config file handle - `key` (const char*) - Key in format section.key (.key for no section) - `default_value` (int32_t) - Default value to return if key isn't found **Returns** - `value` (int32_t) - found value or default value **Examples** ``` static ExtensionResult AppInitialize(ExtensionAppParams* params) { int32_t displayWidth = ConfigFileGetInt(params->m_ConfigFile, "display.width", 640); } ``````cpp static dmExtension::Result AppInitialize(dmExtension::AppParams* params) { int32_t displayWidth = dmConfigFile::GetInt(params->m_ConfigFile, "display.width", 640); } ``` ### ConfigFileGetString *Type:* FUNCTION Get config value as string, returns default if the key isn't found **Parameters** - `config` (HConfigFile) - Config file handle - `key` (const char*) - Key in format section.key (.key for no section) - `default_value` (const char*) - Default value to return if key isn't found **Returns** - `value` (const char*) - found value or default value **Examples** ``` static ExtensionResult AppInitialize(ExtensionAppParams* params) { const char* projectTitle = ConfigFileGetString(params->m_ConfigFile, "project.title", "Untitled"); } ``````cpp static dmExtension::Result AppInitialize(dmExtension::AppParams* params) { const char* projectTitle = dmConfigFile::GetString(params->m_ConfigFile, "project.title", "Untitled"); } ``` ### DM_DECLARE_CONFIGFILE_EXTENSION *Type:* MACRO Declare and register new config file extension to the engine. Each get function should return true if it sets a proper value. Otherwise return false. **Examples** Register a new config file extension: ``` DM_DECLARE_CONFIGFILE_EXTENSION(MyConfigfileExtension, "MyConfigfileExtension", create, destroy, get_string, get_int, get_float); ``` ### FConfigFileCreate *Type:* TYPEDEF Called when config file extension is created **Parameters** - `config` (HConfigFile) - Config file handle ### FConfigFileDestroy *Type:* TYPEDEF Called when config file extension is destroyed **Parameters** - `config` (HConfigFile) - Config file handle ### FConfigFileGetFloat *Type:* TYPEDEF Called when a float is requested from the config file extension **Parameters** - `config` (HConfigFile) - Config file handle - `key` (const char*) - Key in format section.key (.key for no section) - `default_value` (float) - Default value to return if key isn't found - `out` (float*) - Out argument where result is stored if found. **Returns** - `result` (bool) - True if property was found ### FConfigFileGetFloat *Type:* TYPEDEF Called when a float is requested from the config file extension **Parameters** - `config` (HConfigFile) - Config file handle - `key` (const char*) - Key in format section.key (.key for no section) - `default_value` (float) - Default value to return if key isn't found - `out` (float*) - Out argument where result is stored if found. **Returns** - `result` (bool) - True if property was found ### FConfigFileGetInt *Type:* TYPEDEF Called when an integer is requested from the config file extension **Parameters** - `config` (HConfigFile) - Config file handle - `key` (const char*) - Key in format section.key (.key for no section) - `default_value` (int32_t) - Default value to return if key isn't found - `out` (int32_t*) - Out argument where result is stored if found. **Returns** - `result` (bool) - True if property was found ### FConfigFileGetString *Type:* TYPEDEF Called when a string is requested from the config file extension **Parameters** - `config` (HConfigFile) - Config file handle - `key` (const char*) - Key in format section.key (.key for no section) - `default_value` (const char*) - Default value to return if key isn't found - `out` (const char**) - Out argument where result is stored if found. Caller must free() this memory. **Returns** - `result` (bool) - True if property was found ### GetFloat *Type:* FUNCTION Get config value as float, returns default if the key isn't found **Parameters** - `config` (HConfigFile) - Config file handle - `key` (const char*) - Key in format section.key (.key for no section) - `default_value` (int32_t) - Default value to return if key isn't found **Returns** - `value` (int32_t) - found value or default value **Examples** ``` static ExtensionResult AppInitialize(ExtensionAppParams* params) { float gravity = ConfigFileGetFloat(params->m_ConfigFile, "physics.gravity_y", -9.8f); } ``````cpp static dmExtension::Result AppInitialize(dmExtension::AppParams* params) { float gravity = dmConfigFile::GetFloat(params->m_ConfigFile, "physics.gravity_y", -9.8f); } ``` ### GetInt *Type:* FUNCTION Get config value as integer, returns default if the key isn't found **Parameters** - `config` (HConfigFile) - Config file handle - `key` (const char*) - Key in format section.key (.key for no section) - `default_value` (int32_t) - Default value to return if key isn't found **Returns** - `value` (int32_t) - found value or default value **Examples** ``` static ExtensionResult AppInitialize(ExtensionAppParams* params) { int32_t displayWidth = ConfigFileGetInt(params->m_ConfigFile, "display.width", 640); } ``````cpp static dmExtension::Result AppInitialize(dmExtension::AppParams* params) { int32_t displayWidth = dmConfigFile::GetInt(params->m_ConfigFile, "display.width", 640); } ``` ### GetString *Type:* FUNCTION Get config value as string, returns default if the key isn't found **Parameters** - `config` (HConfigFile) - Config file handle - `key` (const char*) - Key in format section.key (.key for no section) - `default_value` (const char*) - Default value to return if key isn't found **Returns** - `value` (const char*) - found value or default value **Examples** ``` static ExtensionResult AppInitialize(ExtensionAppParams* params) { const char* projectTitle = ConfigFileGetString(params->m_ConfigFile, "project.title", "Untitled"); } ``````cpp static dmExtension::Result AppInitialize(dmExtension::AppParams* params) { const char* projectTitle = dmConfigFile::GetString(params->m_ConfigFile, "project.title", "Untitled"); } ``` ### HConfig *Type:* TYPEDEF Each game session has a single config file that holds all parameters from game.project and any overridden values. **Notes** - Properties can be overridden on command line or via the config file extension system. (See [ref:DM_DECLARE_CONFIGFILE_EXTENSION]) ### HConfigFile *Type:* TYPEDEF Each game session has a single config file that holds all parameters from game.project and any overridden values. **Notes** - Properties can be overridden on command line or via the config file extension system. (See [ref:DM_DECLARE_CONFIGFILE_EXTENSION]) # Connection Pool {#apis:engine-dlib-src-dmsdk-dlib-connection_pool-h} **Namespace:** `dmConnectionPool` **Language:** C++ **Type:** Defold C++ **File:** `connection_pool.h` **Source:** `engine/dlib/src/dmsdk/dlib/connection_pool.h` **Include:** `dmsdk/dlib/connection_pool.h` Connection pool ## API ### Close *Type:* FUNCTION Close connection. Use this function whenever an error occur in eg http. **Parameters** - `pool` (dmConnectionPool::HPool) - pool - `connection` (dmConnectionPool::HConnection) ### Delete *Type:* FUNCTION Delete connnection pool **Parameters** - `pool` (dmConnectionPool::HPool) - pool **Returns** - `dmConnectionPool::RESULT_OK` - on success ### Dial *Type:* FUNCTION Connection to a host/port **Parameters** - `pool` (dmConnectionPool::HPool) - pool - `host` (const char*) - host - `port` (uint16_t) - port - `ssl` (bool) - true for ssl connection - `timeout` (int) - The timeout (micro seconds) for the connection and ssl handshake - `connection` (dmConnectionPool::HConnection*) - connection (out) - `sock_res` (dmSocket::Result*) - socket-result code on failure **Returns** - `dmConnectionPool::RESULT_OK` - on success ### Dial *Type:* FUNCTION Connection to a host/port **Parameters** - `pool` (dmConnectionPool::HPool) - pool - `host` (const char*) - host - `port` (uint16_t) - port - `ssl` (bool) - true for ssl connection - `timeout` (int) - The timeout (micro seconds) for the connection and ssl handshake - `cancelflag` (int*) - If set and not null, will make the request early out - `connection` (dmConnectionPool::HConnection*) - connection (out) - `sock_res` (dmSocket::Result*) - socket-result code on failure **Returns** - `dmConnectionPool::RESULT_OK` - on success ### dmConnectionPool::Result *Type:* ENUM Result enumeration. **Members** - `dmConnectionPool::RESULT_OK` - 0 - `dmConnectionPool::RESULT_OUT_OF_RESOURCES` - -1 - `dmConnectionPool::RESULT_SOCKET_ERROR` - -2 - `dmConnectionPool::RESULT_HANDSHAKE_FAILED` - -3 - `dmConnectionPool::RESULT_SHUT_DOWN` - -4 ### GetSocket *Type:* FUNCTION Get socket for connection **Parameters** - `pool` (dmConnectionPool::HPool) - pool - `connection` (dmConnectionPool::HConnection) **Returns** - `return` (dmSocket::Socket) - on success ### GetSSLSocket *Type:* FUNCTION Get secure socket. **Parameters** - `pool` (dmConnectionPool::HPool) - pool - `connection` (dmConnectionPool::HConnection) **Returns** - `return` (dmSSLSocket::Socket) - on success ### HConnection *Type:* TYPEDEF Connection handle ### HPool *Type:* TYPEDEF Connection pool handle ### New *Type:* FUNCTION Create a new connection pool **Parameters** - `params` (dmConnectionPool::Params*) - `pool` (dmConnectionPool::HPool*) - pool (out) **Returns** - `dmConnectionPool::RESULT_OK` - on success ### Params *Type:* STRUCT Creation parameters **Members** - `m_MaxConnections` (int) - Max connection in pool - `m_MaxKeepAlive` (int) - Default max-keep-alive time in seconds ### Return *Type:* FUNCTION Return connection to pool **Parameters** - `pool` (dmConnectionPool::HPool) - pool - `connection` (dmConnectionPool::HConnection) ### Shutdown *Type:* FUNCTION Shuts down all open sockets in the pool and block new connection attempts. The function can be called repeatedly on the same pool until it returns no more connections in use. **Parameters** - `pool` (dmConnectionPool::HPool) - pool - `how` (dmSocket::ShutdownType) - shutdown type to pass to socket shutdown function **Returns** - `current` - number of connections in use # Crypt {#apis:engine-dlib-src-dmsdk-dlib-crypt-h} **Namespace:** `dmCrypt` **Language:** C++ **Type:** Defold C++ **File:** `crypt.h` **Source:** `engine/dlib/src/dmsdk/dlib/crypt.h` **Include:** `dmsdk/dlib/crypt.h` Various hash and encode/decode functions. ## API ### Algorithm *Type:* ENUM encryption algorithm enumeration **Members** - `dmCrypt::ALGORITHM_XTEA` ### dmCrypt::Base64Decode *Type:* FUNCTION Base64 decode a buffer **Notes** - Call this function with *dst_len = 0 to obtain the required buffer size in *dst_len **Parameters** - `src` (const uint8_t*) - The source data to encode - `src_len` (uint32_t) - key The length of source data in bytes - `dst` (uint8_t*) - The destination buffer - `dst_len[in,out]` (uint32_t*) - In: The length of the destination in bytes. Out: The length of the decoded string. **Returns** - `success` (bool) - true if the decoding went ok ### dmCrypt::Base64Encode *Type:* FUNCTION Base64 encode a buffer **Notes** - Call this function with *dst_len = 0 to obtain the required buffer size in *dst_len **Parameters** - `src` (const uint8_t*) - The source data to encode - `src_len` (uint32_t) - key The length of source data in bytes - `dst` (uint8_t*) - The destination buffer - `dst_len[in,out]` (uint32_t*) - In: The length of the destination in bytes. Out: The length of the encoded string. **Returns** - `success` (bool) - true if the encoding went ok ### dmCrypt::Decrypt *Type:* FUNCTION Decrypt data in place **Parameters** - `algo` (dmCrypt::Algorithm) - algorithm - `data` (const uint8_t*) - data - `datalen` (uint32_t) - data length in bytes - `key` (const uint8_t*) - key - `keylen` (uint32_t) - key length **Returns** - `result` (dmCrypt::Result) - the decryption result ### dmCrypt::Encrypt *Type:* FUNCTION Encrypt data in place **Parameters** - `algo` (dmCrypt::Algorithm) - algorithm - `data` (const uint8_t*) - data - `datalen` (uint32_t) - data length in bytes - `key` (const uint8_t*) - key - `keylen` (uint32_t) - key length **Returns** - `result` (dmCrypt::Result) - the encryption result ### dmCrypt::HashMd5 *Type:* FUNCTION Hash buffer using MD5 **Parameters** - `buf` (const uint8_t*) - The source data to hash - `buflen` (uint32_t) - key The length of source data in bytes - `digest` (const uint8_t*) - The destination buffer (16 bytes) ### dmCrypt::HashSha1 *Type:* FUNCTION Hash buffer using SHA1 **Parameters** - `buf` (const uint8_t*) - The source data to hash - `buflen` (uint32_t) - The length of source data in bytes - `digest` (uint8_t*) - The destination buffer (20 bytes) ### dmCrypt::HashSha256 *Type:* FUNCTION Hash buffer using SHA256 **Parameters** - `buf` (const uint8_t*) - The source data to hash - `buflen` (uint32_t) - key The length of source data in bytes - `digest` (uint8_t*) - The destination buffer (32 bytes) ### dmCrypt::HashSha512 *Type:* FUNCTION Hash buffer using SHA512 **Parameters** - `buf` (const uint8_t*) - The source data to hash - `buflen` (uint32_t) - key The length of source data in bytes - `digest` (uint8_t*) - The destination buffer (64 bytes) ### Result *Type:* ENUM result enumeration **Members** - `dmCrypt::RESULT_OK` - = 0 - `dmCrypt::RESULT_ERROR` - = 1 # Double linked list structs and functions {#apis:engine-dlib-src-dmsdk-dlib-double_linked_list-h} **Namespace:** `dmDoubleLinkedList` **Language:** C++ **Type:** Defold C++ **File:** `double_linked_list.h` **Source:** `engine/dlib/src/dmsdk/dlib/double_linked_list.h` **Include:** `dmsdk/dlib/double_linked_list.h` Double linked list structs and functions ## API ### dmDoubleLinkedList::ListAdd *Type:* FUNCTION Added new list element as a head of the list **Parameters** - `list` (dmDoubleLinkedList::List*) - the list - `item` (dmDoubleLinkedList::ListNode*) - new list element ### dmDoubleLinkedList::ListGetFirst *Type:* FUNCTION Get the first element of the list. If the list is empty (tail == head) returns 0. **Parameters** - `list` (dmDoubleLinkedList::List*) - the list **Returns** - `first_element` (dmDoubleLinkedList::ListNode*) - the first element of the list. If the list is empty (tail == head) returns 0 ### dmDoubleLinkedList::ListGetLast *Type:* FUNCTION Get the last element of the list. If the list is empty (tail == head) returns 0. **Parameters** - `list` (dmDoubleLinkedList::List*) - the list **Returns** - `last_element` (dmDoubleLinkedList::ListNode*) - the last element of the list. If the list is empty (tail == head) returns 0 ### dmDoubleLinkedList::ListInit *Type:* FUNCTION Initialize empty double linked list **Parameters** - `list` (dmDoubleLinkedList::List*) - the list ### dmDoubleLinkedList::ListRemove *Type:* FUNCTION Remove item from the list. Doesn't deallocate memory allocated for the item. If element is not in the list function doesn't affect linked list. **Parameters** - `list` (dmDoubleLinkedList::List*) - the list - `item` (dmDoubleLinkedList::ListNode*) - removed item # FileDescriptor {#apis:engine-dlib-src-dmsdk-dlib-file_descriptor-h} **Namespace:** `dmFileDescriptor` **Language:** C++ **Type:** Defold C++ **File:** `file_descriptor.h` **Source:** `engine/dlib/src/dmsdk/dlib/file_descriptor.h` **Include:** `dmsdk/dlib/file_descriptor.h` File Descriptor functions. ## API ### Poller *Type:* STRUCT Poller ### PollerClearEvent *Type:* FUNCTION Clear event from poller. **Parameters** - `poller` (dmFileDescriptor::Poller*) - Poller - `event` (dmFileDescriptor::PollEvent) - Event to clear - `fd` (int) - File descriptor to clear **Returns** - `return` (void) ### PollerHasEvent *Type:* FUNCTION Check if event exists for file descriptor **Parameters** - `poller` (dmFileDescriptor::Poller*) - Poller - `event` (dmFileDescriptor::PollEvent) - Event to check - `fd` (int) - File descriptor to clear **Returns** - `return` (bool) - True if event exists. ### PollerReset *Type:* FUNCTION Reset poller. **Parameters** - `spoller` (dmFileDescriptor::Poller*) - Poller **Returns** - `return` (void) ### PollerSetEvent *Type:* FUNCTION Set file descriptor event to poll for **Parameters** - `poller` (dmFileDescriptor::Poller*) - Poller - `event` (dmFileDescriptor::PollEvent) - Event to set - `fd` (int) - File descriptor to clear **Returns** - `return` (void) ### PollEvent *Type:* ENUM Poll events **Members** - `EVENT_READ` - `EVENT_WRITE` - `EVENT_ERROR` ### Wait *Type:* FUNCTION Wait for event **Parameters** - `poller` (dmFileDescriptor::Poller*) - Poller - `timeout` (int) - Timeout. For blocking pass -1. (milliseconds) **Returns** - `return` (int) - Non-negative value on success, 0 on timeout and -1 on error with errno set to indicate the error # Hashtable {#apis:engine-dlib-src-dmsdk-dlib-hashtable-h} **Namespace:** `Hashtable` **Language:** C++ **Type:** Defold C++ **File:** `hashtable.h` **Source:** `engine/dlib/src/dmsdk/dlib/hashtable.h` **Include:** `dmsdk/dlib/hashtable.h` Hash table ## API ### Capacity *Type:* FUNCTION Hashtable capacity. Maximum number of entries possible to store in table **Returns** - `return` (uint32_t) - the capacity of the table ### Clear *Type:* FUNCTION Removes all the entries from the table. ### dmHashTable *Type:* CLASS Hashtable with chaining for collision resolution, memcpy-copy semantics (POD types) and 32-bit indicies instead of pointers. (NUMA-friendly) **Notes** - The key type needs to support == and % operators **Template Parameters** - `KEY` - `T` ### dmHashTable *Type:* FUNCTION Constructor. Create an empty hashtable with zero capacity and zero hashtable (buckets) ### dmHashTable *Type:* FUNCTION Creates a hashtable array with user allocated memory. **Notes** - User allocated arrays can not change capacity. **Parameters** - `user_allocated` (void*) - Pointer to user allocated continous data-block ((table_sizesizeof(uint32_t)) + (capacitysizeof(dmHashTable::Entry)) - `table_size` (uint32_t) - Hashtable size, ie number of buckets. table_size < 0xffffffff - `capacity` (uint32_t) - Capacity. capacity < 0xffffffff ### dmHashTable16 *Type:* CLASS Specialized hash table with uint16_t as keys ### dmHashTable32 *Type:* CLASS Specialized hash table with uint32_t as keys ### dmHashTable64 *Type:* CLASS Specialized hash table with uint64_t as keys ### Empty *Type:* FUNCTION Check if the table is empty **Returns** - `true` - if the table is empty ### Erase *Type:* FUNCTION Remove key/value pair. **Notes** - Only valid if key exists in table **Parameters** - `key` (KEY) - Key to remove ### Full *Type:* FUNCTION Check if the table is full **Returns** - `true` - if the table is full ### Get *Type:* FUNCTION Get pointer to value from key **Parameters** - `key` (KEY) - Key **Returns** - `value` (T*) - Pointer to value. NULL if the key/value pair doesn't exist. ### GetIterator *Type:* FUNCTION Get an iterator for the key/value pairs **Returns** - `iterator` (dmHashTable::Iterator) - the iterator **Examples** ``` dmHashTable::Iterator iter = ht.GetIterator(); while(iter.Next()) { printf("%s: %d\n", dmHashReverseSafe64(iter.GetKey()), iter.GetValue()); } ``` ### Iterate *Type:* FUNCTION Iterate over all entries in table **Template Parameters** - `CONTEXT` **Parameters** - `call_back` (void*) - Call-back called for every entry - `context` (CONTEXT*) - Context ### Iterator *Type:* STRUCT Iterator to the key/value pairs of a hash table **Members** - `GetKey()` - `GetValue()` ### OffsetCapacity *Type:* FUNCTION Relative change of capacity Equivalent to SetCapacity(Capacity() + offset). Only allowed for auto-allocated hash tables and will result in a new dynamic allocation **Parameters** - `offset` (uint32_t) - relative amount of elements to change the capacity ### Put *Type:* FUNCTION Put key/value pair in hash table. NOTE: The method will "assert" if the hashtable is full. **Parameters** - `key` (KEY) - Key - `value` (const T&) - Value ### SetCapacity *Type:* FUNCTION Set hashtable capacity. New capacity must be greater or equal to current capacity **Parameters** - `table_size` (uint32_t) - Hashtable size, ie number of buckets. table_size < 0xffffffff - `capacity` (uint32_t) - Capacity. capacity < 0xffffffff ### Size *Type:* FUNCTION Number of entries stored in table. (not the actual hashtable size) **Returns** - `Number` - of entries. ### Swap *Type:* FUNCTION Swaps the contents of two hash tables **Parameters** - `other` (dmHashTable&) - the other table # Http Client {#apis:engine-dlib-src-dmsdk-dlib-http_client-h} **Namespace:** `dmHttpClient` **Language:** C++ **Type:** Defold C++ **File:** `http_client.h` **Source:** `engine/dlib/src/dmsdk/dlib/http_client.h` **Include:** `dmsdk/dlib/http_client.h` Http client functions. ## API ### ParseHeader *Type:* FUNCTION Parse the header data and make callbacks for each header/version entry and the start of the body. **Notes** - This function is destructive to the input data. **Parameters** - `header_str` (char*) - http response headers. Must be a null terminated string. - `user_data` (const void*) - user data to the callbacks. - `end_of_receive` (bool) - true if there is no more data - `version_cbk` (function) - callback for the http version void (version_cbk)(void user_data, int major, int minor, int status, const char* status_str); - `header_cbk` (function) - callback for each header/value pair void (header_cbk)(void user_data, const char key, const char value); - `body_cbk` (function) - callback to note the start offset of the body data. void (body_cbk)(void user_data, int offset) **Returns** - `result` (dmHttpClient::ParseResult) - the parse result ### ParseResult *Type:* ENUM Header parse result enumeration. **Members** - `dmHttpClient::PARSE_RESULT_NEED_MORE_DATA` - = 1 - `dmHttpClient::PARSE_RESULT_OK` - = 0 - `dmHttpClient::PARSE_RESULT_SYNTAX_ERROR` - = -1 # Image {#apis:engine-dlib-src-dmsdk-dlib-image-h} **Namespace:** `dmImage` **Language:** C++ **Type:** Defold C++ **File:** `image.h` **Source:** `engine/dlib/src/dmsdk/dlib/image.h` **Include:** `dmsdk/dlib/image.h` Image API functions. ## API ### GetAstcBlockSize *Type:* FUNCTION Get the block size **Parameters** - `mem` (void*) - the .astc memory (including the header) - `memsize` (uint32_t) - the length of the memory blob - `width` (uint32_t*) - (out) the block width - `height` (uint32_t*) - (out) the block height - `depth` (uint32_t*) - (out) the block depth **Returns** - `result` (bool) - true if it's an astc file ### GetAstcDimensions *Type:* FUNCTION Get the astc image size **Parameters** - `mem` (void*) - the .astc memory (including the header) - `memsize` (uint32_t) - the length of the memory blob - `width` (uint32_t*) - (out) the block width - `height` (uint32_t*) - (out) the block height - `depth` (uint32_t*) - (out) the block depth **Returns** - `result` (bool) - true if it's an astc file ### Result *Type:* ENUM result enumeration **Members** - `dmImage::RESULT_OK` - = 0 - `dmImage::RESULT_UNSUPPORTED_FORMAT` - = -1 - `dmImage::RESULT_IMAGE_ERROR` - = -2 ### Type *Type:* ENUM type enumeration **Members** - `dmImage::TYPE_RGB` - = 0 - `dmImage::TYPE_RGBA` - = 1 - `dmImage::TYPE_LUMINANCE` - = 2 - `dmImage::TYPE_LUMINANCE_ALPHA` - = 3 # Intersection structs and functions {#apis:engine-dlib-src-dmsdk-dlib-intersection-h} **Namespace:** `dmIntersection` **Language:** C++ **Type:** Defold C++ **File:** `intersection.h` **Source:** `engine/dlib/src/dmsdk/dlib/intersection.h` **Include:** `dmsdk/dlib/intersection.h` Intersection math structs and functions ## API ### CreateFrustumFromMatrix *Type:* FUNCTION Constructs a dmIntersection::Frustum from a View*Projection matrix **Parameters** - `m` (dmVMath::Matrix4&) - The matrix. Usually a "ViewProj" matrix - `normalize` (bool) - true if the normals should be normalized **Returns** - `frustum` (dmIntersection::Frustum&) - the frustum output ### DistanceToPlane *Type:* FUNCTION Returns the closest distance between a plane and a position **Parameters** - `plane` (dmIntersection::Plane) - plane equation - `pos` (dmVMath::Point3) - position **Returns** - `distance` (float) - closest distance between plane and position ### Frustum *Type:* STRUCT Frustum **Notes** - The plane normals point inwards **Members** - `m_Planes` (dmIntersection::Plane[6) - ] plane equations: // left, right, bottom, top, near, far ### Plane *Type:* TYPEDEF Plane struct (currently an alias for dmVMath::Vector4) ### TestFrustumOBB *Type:* FUNCTION Tests intersection between a frustum and an oriented bounding box (OBB) **Parameters** - `frustum` (dmIntersection::Frustum&) - the frustum - `world` (dmVMath::Matrix4&) - The world transform of the OBB - `aabb_min` (dmVMath::Vector3&) - the minimum corner of the object. In local space. - `aabb_max` (dmVMath::Vector3&) - the maximum corner of the object. In local space. - `skip_near_far` (bool) - if true, the near+far planes of the frustum are ignored **Returns** - `intersects` (bool) - Returns true if the objects intersect ### TestFrustumPoint *Type:* FUNCTION Tests intersection between a frustum and a point **Parameters** - `frustum` (dmIntersection::Frustum&) - the frustum - `pos` (dmVMath::Point3&) - the position - `skip_near_far` (bool) - if true, the near+far planes of the frustum are ignored **Returns** - `intersects` (bool) - Returns true if the objects intersect ### TestFrustumSphere *Type:* FUNCTION Tests intersection between a frustum and a sphere **Parameters** - `frustum` (dmIntersection::Frustum&) - the frustum - `pos` (dmVMath::Point3&) - the center position of the sphere - `radius` (float) - the radius of the sphere - `skip_near_far` (bool) - if true, the near+far planes of the frustum are ignored **Returns** - `intersects` (bool) - Returns true if the objects intersect ### TestFrustumSphere *Type:* FUNCTION Tests intersection between a frustum and a sphere **Parameters** - `frustum` (dmIntersection::Frustum&) - the frustum - `pos` (dmVMath::Vector4&) - the center position of the sphere. The w component must be 1. - `radius` (float) - the radius of the sphere - `skip_near_far` (bool) - if true, the near+far planes of the frustum are ignored **Returns** - `intersects` (bool) - Returns true if the objects intersect ### TestFrustumSphereSq *Type:* FUNCTION Tests intersection between a frustum and a sphere **Parameters** - `frustum` (dmIntersection::Frustum&) - the frustum - `pos` (dmVMath::Point3&) - the center position of the sphere - `radius_sq` (float) - the squared radius of the sphere - `skip_near_far` (bool) - if true, the near+far planes of the frustum are ignored **Returns** - `intersects` (bool) - Returns true if the objects intersect ### TestFrustumSphereSq *Type:* FUNCTION Tests intersection between a frustum and a sphere **Parameters** - `frustum` (dmIntersection::Frustum&) - the frustum - `pos` (dmVMath::Vector4&) - the center position of the sphere. The w component must be 1. - `radius_sq` (float) - the squared radius of the sphere - `skip_near_far` (bool) - if true, the near+far planes of the frustum are ignored **Returns** - `intersects` (bool) - Returns true if the objects intersect # Log {#apis:engine-dlib-src-dmsdk-dlib-log-h} **Namespace:** `Log` **Language:** C++ **Type:** Defold C++ **File:** `log.h` **Source:** `engine/dlib/src/dmsdk/dlib/log.h` **Include:** `dmsdk/dlib/log.h` Logging functions. ## Notes - Log functions will be omitted (NOP) for release builds - Prefer these functions over `printf` since these can print to the platform specific logs ## API ### DLIB_LOG_DOMAIN *Type:* MACRO If DLIB_LOG_DOMAIN is defined the value of the defined is printed after severity. Otherwise DEFAULT will be printed. **Notes** - Extensions do not need to set this since they get their own logging domain automatically **Examples** ``` #define DLIB_LOG_DOMAIN "MyOwnDomain" #include ``` ### dmLogDebug *Type:* FUNCTION Debug messages are temporary log instances used when debugging a certain behavior Use dmLogOnceDebug for one-shot logging **Parameters** - `format` (const char*) - Format string - `args` (...) - Format string args (variable arg list) **Returns** - `return` (void) ### dmLogError *Type:* FUNCTION Error messages are used in cases where an recoverable error has occurred. Use dmLogOnceError for one-shot logging **Parameters** - `format` (const char*) - Format string - `args` (...) - Format string args (variable arg list) **Returns** - `return` (void) ### dmLogFatal *Type:* FUNCTION Fatal messages are used in cases where an unrecoverable error has occurred. Use dmLogOnceFatal for one-shot logging **Parameters** - `format` (const char*) - Format string - `args` (...) - Format string args (variable arg list) **Returns** - `return` (void) ### dmLogFinalize *Type:* FUNCTION finalize the logging system. ### dmLogGetLevel *Type:* FUNCTION Get log system severity level. **Returns** - `severity` (LogSeverity) - Current log system severity level ### dmLogInfo *Type:* FUNCTION Info messages are used to inform the developers of relevant information Use dmLogOnceInfo for one-shot logging **Parameters** - `format` (const char*) - Format string - `args` (...) - Format string args (variable arg list) **Returns** - `return` (void) ### dmLogInitialize *Type:* FUNCTION Running this function is only required in order to start the log server. The function never fails even if the log server cannot be started. Any startup errors are reported to stderr. **Parameters** - `params` (LogParams*) - log parameters ### dmLogRegisterListener *Type:* FUNCTION Registers a log listener. This listener receive logs even in release bundle. **Notes** - Any calls to dmLogInfo et al from within the calllback will be ignored **Parameters** - `listener` (FLogListener) ### dmLogSetLevel *Type:* FUNCTION Set log system severity level. **Parameters** - `severity` (LogSeverity) - Log system severity level to set ### dmLogUnregisterListener *Type:* FUNCTION Unregisters a log listener. **Parameters** - `listener` (FLogListener) ### dmLogUserDebug *Type:* FUNCTION Debug messages are temporary log instances used when debugging a certain behavior Use dmLogOnceUserDebug for one-shot logging **Parameters** - `format` (const char*) - Format string - `args` (...) - Format string args (variable arg list) **Returns** - `return` (void) ### dmLogWarning *Type:* FUNCTION Warning messages are used to inform the developers about potential problems which can cause errors. Use dmLogOnceWarning for one-shot logging **Parameters** - `format` (const char*) - Format string - `args` (...) - Format string args (variable arg list) **Returns** - `return` (void) ### FLogListener *Type:* TYPEDEF dmLog listener function type. Provides all logs from dmLog* functions and print/pprint Lua functions. Used with dmLogRegisterListener() and dmLogUnregisterListener() **Parameters** - `severity` (LogSeverity) - `domain` (const char*) - `formatted_string` (const char*) - null terminated string ### LogParams *Type:* STRUCT Parameters for dmLogInitialize(). ### LogSeverity *Type:* ENUM Log severity **Members** - `LOG_SEVERITY_DEBUG` - `LOG_SEVERITY_USER_DEBUG` - `LOG_SEVERITY_INFO` - `LOG_SEVERITY_WARNING` - `LOG_SEVERITY_ERROR` - `LOG_SEVERITY_FATAL` # Math {#apis:engine-dlib-src-dmsdk-dlib-math-h} **Namespace:** `dmMath` **Language:** C++ **Type:** Defold C++ **File:** `math.h` **Source:** `engine/dlib/src/dmsdk/dlib/math.h` **Include:** `dmsdk/dlib/math.h` Math functions. ## API ### Abs *Type:* FUNCTION Abs function **Template Parameters** - `T` **Parameters** - `x` (T) **Returns** - `v` (T) - Absolute value of x ### Clamp *Type:* FUNCTION Clamp function **Template Parameters** - `T` **Parameters** - `v` (T) - Value to clamp - `min` (T) - Lower bound - `max` (T) - Upper bound **Returns** - `v` (T) - Value closest to v inside the range [min, max] ### Max *Type:* FUNCTION Max function **Template Parameters** - `T` **Parameters** - `a` (T) - Value a - `b` (T) - Value b **Returns** - `v` (T) - Max of a and b ### Min *Type:* FUNCTION Min function **Template Parameters** - `T` **Parameters** - `a` (T) - Value a - `b` (T) - Value b **Returns** - `v` (T) - Min of a and b ### Select *Type:* FUNCTION Select one of two values depending on the sign of another. **Template Parameters** - `T` **Parameters** - `x` (T) - Value to test for positiveness - `a` (T) - Result if test succeeded - `b` (T) - Result if test failed **Returns** - `v` (T) - a when x >= 0, b otherwise # Memory {#apis:engine-dlib-src-dmsdk-dlib-memory-h} **Namespace:** `dmMemory` **Language:** C++ **Type:** Defold C++ **File:** `memory.h` **Source:** `engine/dlib/src/dmsdk/dlib/memory.h` **Include:** `dmsdk/dlib/memory.h` Memory allocation functions ## API ### AlignedFree *Type:* FUNCTION Frees a block of memory that was allocated with dmMemory::AlignedMalloc **Parameters** - `memptr` (void*) - A pointer to the memory block that was returned by dmMemory::AlignedMalloc ### AlignedMalloc *Type:* FUNCTION Allocate size bytes of uninitialized storage whose alignment is specified by alignment. **Parameters** - `memptr` (void**) - Pointer to a void* where the allocated pointer address should be stored. - `alignment` (uint32_t) - The alignment value, which must be an integer power of 2. - `size` (uint32_t) - Size of the requested memory allocation. **Returns** - `result` (Result) - Returns RESULT_OK on success, RESULT_INVAL if alignment is not a power of 2 and RESULT_NOMEM if out of memory. ### Result *Type:* ENUM Aligned memory allocation result **Members** - `dmMemory::RESULT_OK` - 0 - `dmMemory::RESULT_INVAL` - -1 - `dmMemory::RESULT_NOMEM` - -2 # Message {#apis:engine-dlib-src-dmsdk-dlib-message-h} **Namespace:** `dmMessage` **Language:** C++ **Type:** Defold C++ **File:** `message.h` **Source:** `engine/dlib/src/dmsdk/dlib/message.h` **Include:** `dmsdk/dlib/message.h` Api for sending messages ## API ### dmMessage::Result *Type:* ENUM Result enum **Members** - `RESULT_OK` - = 0 - `RESULT_SOCKET_EXISTS` - = -1 - `RESULT_SOCKET_NOT_FOUND` - = -2 - `RESULT_SOCKET_OUT_OF_RESOURCES` - = -3 - `RESULT_INVALID_SOCKET_NAME` - = -4 - `RESULT_MALFORMED_URL` - = -5 - `RESULT_NAME_OK_SOCKET_NOT_FOUND` - = -6 ### dmMessage::StringURL *Type:* STRUCT Helper struct for parsing a string of the form "socket:path#fragment" **Notes** - The sizes do not include the null character. There is no null character since the dmMessage::ParseURL is non destructive. **Members** - `m_Socket` (const char*) - The socket - `m_SocketSize` (uint32_t) - The socket length - `m_Path` (const char*) - The path - `m_PathSize` (uint32_t) - The path length - `m_Fragment` (const char*) - The fragment - `m_FragmentSize` (uint32_t) - The fragment length ### dmMessage::URL *Type:* STRUCT URL specifying a sender/receiver of messages **Notes** - Currently has a hard limit of 32 bytes - This struct is a part of the save file APi (see script_table.cpp) ### dmMMessage::MessageDestroyCallback *Type:* TYPEDEF A callback for messages that needs cleanup after being dispatched. E.g. for freeing resources/memory. ### GetFragment *Type:* FUNCTION Get the message fragment **Parameters** - `url` (dmMessage::URL) - url **Returns** - `fragment` (dmhash_t) ### GetPath *Type:* FUNCTION Get the message path **Parameters** - `url` (dmMessage::URL) - url **Returns** - `path` (dmhash_t) ### GetSocket *Type:* FUNCTION Get the message socket **Parameters** - `url` (dmMessage::URL) - url **Returns** - `socket` (dmMessage::HSocket) ### GetSocketName *Type:* FUNCTION Get socket name **Parameters** - `socket` (dmMessage::HSocket) - Socket **Returns** - `name` (const char*) - socket name. 0 if it was not found ### GetSocketNameHash *Type:* FUNCTION Get socket name hash **Parameters** - `socket` (dmMessage::HSocket) - Socket **Returns** - `name_hash` (dmhash_t) - socket name hash. 0 if it was not found ### HSocket *Type:* TYPEDEF Socket handle ### IsSocketValid *Type:* FUNCTION Tests if a socket is valid (not deleted). **Parameters** - `socket` (dmMessage::HSocket) - Socket **Returns** - `result` (bool) - if the socket is valid or not ### Message *Type:* STRUCT ### Message *Type:* STRUCT Message data desc used at dispatch callback. When a message is posted, the actual object is copied into the sockets internal buffer. **Members** - `m_Sender` (dmMessage::URL) - Sender uri - `m_Receiver` (dmMessage::URL) - Receiver uri - `m_Id` (dmhash_t) - Unique id of message - `m_UserData1` (uintptr_t) - User data pointer - `m_UserData2` (uintptr_t) - User data pointer - `m_Descriptor` (uintptr_t) - User specified descriptor of the message data - `m_DataSize` (uint32_t) - Size of message data in bytes - `m_Next` (dmMessage::Message*) - Ptr to next message (or 0 if last) - `m_DestroyCallback` (dmMessage::MessageDestroyCallback) - If set, will be called after each dispatch - `m_Data` (uint8_t*) - Payload ### ParseUrl *Type:* FUNCTION Convert a string to a URL struct **Notes** - No allocation occurs, thus no cleanup is needed. **Parameters** - `uri` (const char*) - string of the format ][path[#fragment] - `out` (dmMessage::StringUrl) - url in string format, must not be 0x0 **Returns** - `-` - RESULT_OK on success - RESULT_MALFORMED_URL if the uri could not be parsed ### ResetUrl *Type:* FUNCTION Resets the given URL to default values. **Notes** - Previously the URL wasn't reset in the constructor and certain calls to ResetURL might currently be redundant **Parameters** - `url` (dmMessage::URL) - URL to reset ### SetFragment *Type:* FUNCTION Set the message fragment **Parameters** - `url` (dmMessage::URL) - url - `fragment` (dmhash_t) ### SetPath *Type:* FUNCTION Set the message path **Parameters** - `url` (dmMessage::URL) - url - `path` (dmhash_t) ### SetSocket *Type:* FUNCTION Set the socket **Parameters** - `url` (dmMessage::URL) - url - `socket` (dmMessage::HSocket) # Mutex {#apis:engine-dlib-src-dmsdk-dlib-mutex-h} **Namespace:** `dmMutex` **Language:** C++ **Type:** Defold C++ **File:** `mutex.h` **Source:** `engine/dlib/src/dmsdk/dlib/mutex.h` **Include:** `dmsdk/dlib/mutex.h` API for platform independent mutex synchronization primitive. ## API ### DM_MUTEX_OPTIONAL_SCOPED_LOCK *Type:* MACRO If mutex is not null, Will lock the mutex and automatically unlock it at the end of the scope. Since using threads is optional, we want to make it easy to switch on/off the mutex behavior **Parameters** - `mutex` (dmMutex::HMutex) - Mutex handle to lock, or null. ### DM_MUTEX_SCOPED_LOCK *Type:* MACRO Will lock a Mutex and automatically unlock it at the end of the scope. **Parameters** - `mutex` (dmMutex::HMutex) - Mutex handle to lock. ### dmMutex::Delete *Type:* FUNCTION Deletes a HMutex. **Parameters** - `mutex` (dmMutex::HMutex) - Mutex handle to delete. ### dmMutex::HMutex *Type:* TYPEDEF ``` typedef struct Mutex* HMutex; ``` ### dmMutex::Lock *Type:* FUNCTION Lock a HMutex, will block until mutex is unlocked if already locked elsewhere. **Parameters** - `mutex` (dmMutex::HMutex) - Mutex handle to lock. ### dmMutex::New *Type:* FUNCTION Creates a new HMutex. **Returns** - `mutex` (dmMutex::HMutex) - A new Mutex handle. ### dmMutex::TryLock *Type:* FUNCTION Tries to lock a HMutex, if mutex is already locked it will return false and continue without locking the mutex. **Parameters** - `mutex` (dmMutex::HMutex) - Mutex handle to lock. **Returns** - `result` (bool) - True if mutex was successfully locked, false otherwise. ### dmMutex::Unlock *Type:* FUNCTION Unlock a HMutex. **Parameters** - `mutex` (dmMutex::HMutex) - Mutex handle to unlock. # ObjectPool {#apis:engine-dlib-src-dmsdk-dlib-object_pool-h} **Namespace:** `ObjectPool` **Language:** C++ **Type:** Defold C++ **File:** `object_pool.h` **Source:** `engine/dlib/src/dmsdk/dlib/object_pool.h` **Include:** `dmsdk/dlib/object_pool.h` Object Pool API documentation ## API ### Alloc *Type:* FUNCTION Allocate a new object **Returns** - `index` (uint32_t) - logical index ### Capacity *Type:* FUNCTION **Returns** - `capacity` (uint32_t) - maximum number of objects ### dmObjectPool *Type:* STRUCT Object pool data-structure with the following properties - Mapping from logical index to physical index - Logical index does not changes - Allocated objects are contiguously laid out in memory Loop of m_Objects [0..Size()-1] times to iterate all objects - Internal physical order is not preserved and a direct consequence of the contiguous property **Template Parameters** - `T` ### dmObjectPool *Type:* FUNCTION Constructor ### Free *Type:* FUNCTION Returns object index to the object pool **Parameters** - `index` (uint32_t) - index of object - `clear` (bool) - If set, memset's the object memory ### Full *Type:* FUNCTION Checks if the pool is full **Returns** - `result` (bool) - returns true if the pool is full ### Get *Type:* FUNCTION Get object from logical index **Parameters** - `index` (uint32_t) - index of the object **Returns** - `object` (T&) - a reference to the object ### GetPtr *Type:* FUNCTION Get object pointer from logical index **Parameters** - `index` (uint32_t) - index of the object **Returns** - `object` (T*) - a pointer to the object. Null if the logical index wasn't valid ### GetRawObjects *Type:* FUNCTION Get the array of currently active objects **Notes** - The order of objects in this array may change if Alloc() or Free() has been called **Returns** - `object` (dmArray&) - a reference to the array of objects ### OffsetCapacity *Type:* FUNCTION Grow by an amount. **Parameters** - `grow` (uint32_t) - number of items to grow ### Set *Type:* FUNCTION Set object from logical index **Parameters** - `index` (uint32_t) - index of object - `object` (T&) - reference ot object. THe object stored is copied by value. ### SetCapacity *Type:* FUNCTION Set capacity. New capacity must be >= old_capacity **Parameters** - `capacity` (uint32_t) - max number of objects to store ### Size *Type:* FUNCTION Get number of objects currently stored **Returns** - `size` (uint32_t) - returns the number of objects currently stored # Profile {#apis:engine-dlib-src-dmsdk-dlib-profile-h} **Namespace:** `dmProfile` **Language:** C++ **Type:** Defold C++ **File:** `profile.h` **Source:** `engine/dlib/src/dmsdk/dlib/profile.h` **Include:** `dmsdk/dlib/profile.h` Profiling macros ## API ### DM_PROFILE *Type:* MACRO Adds a profiling scope. Excluded by default in release builds. **Parameters** - `a` (const char*) - A name for the scope **Examples** Profile a scope ``` { DM_PROFILE("DoWork"); DoWork1(); DoWork2(); } ``` ### DM_PROFILE_DYN *Type:* MACRO Adds a profiling scope. Excluded by default in release builds. Accepts a name cache value for performance. **Parameters** - `a` (const char*) - The scope name - `a` (uint64_t*) - The scope name hash value pointer. May be 0. **Examples** Create a dynamic profiling scope ``` { DM_PROFILE_DYN(work->m_Name, &work->m_NameHash); work->DoWork(); } ``` ### DM_PROFILE_TEXT *Type:* MACRO Send text to the profiler **Notes** - The max length of the text is DM_PROFILE_TEXT_LENGTH (1024) **Parameters** - `a` (const char*) - The format string - `a` (va_list) - The variable argument list **Examples** Send a string to the profiler ``` DM_PROFILE_TEXT("Some value: %d", value); ``` ### DM_PROPERTY_ADD_F32 *Type:* MACRO Add a value to float property **Parameters** - `name` (symbol) - The property - `value` (float) - The value **Examples** ``` DM_PROPERTY_ADD_F32(rmtp_MyValue, 1.5); ``` ### DM_PROPERTY_ADD_F64 *Type:* MACRO Add a value to double property **Parameters** - `name` (symbol) - The property - `value` (double) - The value **Examples** ``` DM_PROPERTY_ADD_F64(rmtp_MyValue, 1.5); ``` ### DM_PROPERTY_ADD_S32 *Type:* MACRO Add a value to int32_t property **Parameters** - `name` (symbol) - The property - `value` (int32_t) - The value **Examples** ``` DM_PROPERTY_ADD_S32(rmtp_MyValue, -1); ``` ### DM_PROPERTY_ADD_S64 *Type:* MACRO Add a value to int64_t property **Parameters** - `name` (symbol) - The property - `value` (int64_t) - The value **Examples** ``` DM_PROPERTY_ADD_S64(rmtp_MyValue, -1); ``` ### DM_PROPERTY_ADD_U32 *Type:* MACRO Add a value to uint32_t property **Parameters** - `name` (symbol) - The property - `value` (uint32_t) - The value **Examples** ``` DM_PROPERTY_ADD_U32(rmtp_MyValue, 1); ``` ### DM_PROPERTY_ADD_U64 *Type:* MACRO Add a value to uint64_t property **Parameters** - `name` (symbol) - The property - `value` (uint64_t) - The value **Examples** ``` DM_PROPERTY_ADD_U64(rmtp_MyValue, 1); ``` ### DM_PROPERTY_BOOL *Type:* MACRO Declare a property of type bool **Parameters** - `name` (symbol) - The property symbol/name - `default` (bool) - The default value - `flags` (uint32_t) - The flags. Either PROFILE_PROPERTY_NONE or PROFILE_PROPERTY_FRAME_RESET. PROFILE_PROPERTY_FRAME_RESET makes the value reset each frame. - `desc` (const char*) - The description - `group` (ProfileIdx*) - The parent group. May be 0. **Examples** ``` DM_PROPERTY_BOOL(rmtp_MyBool, 0, PROFILE_PROPERTY_FRAME_RESET, "true or false", &rmtp_MyGroup); ``` ### DM_PROPERTY_EXTERN *Type:* MACRO Declare an extern property **Parameters** - `name` (symbol) - The symbol name **Examples** Use a property declared elsewhere in the same library ``` DM_PROPERTY_EXTERN(rmtp_GameObject); DM_PROPERTY_U32(rmtp_ComponentsAnim, 0, PROFILE_PROPERTY_FRAME_RESET, "#", &rmtp_GameObject); ``` ### DM_PROPERTY_F32 *Type:* MACRO Declare a property of type float **Parameters** - `name` (symbol) - The property symbol/name - `default` (float) - The default value - `flags` (uint32_t) - The flags. Either PROFILE_PROPERTY_NONE or PROFILE_PROPERTY_FRAME_RESET. PROFILE_PROPERTY_FRAME_RESET makes the value reset each frame. - `desc` (const char*) - The description - `group` (ProfileIdx*) - The parent group. May be 0. **Examples** ``` DM_PROPERTY_F32(rmtp_MyValue, 0, PROFILE_PROPERTY_FRAME_RESET, "a value", &rmtp_MyGroup); ``` ### DM_PROPERTY_F64 *Type:* MACRO Declare a property of type double **Parameters** - `name` (symbol) - The property symbol/name - `default` (double) - The default value - `flags` (uint32_t) - The flags. Either PROFILE_PROPERTY_NONE or PROFILE_PROPERTY_FRAME_RESET. PROFILE_PROPERTY_FRAME_RESET makes the value reset each frame. - `desc` (const char*) - The description - `group` (ProfileIdx*) - The parent group. May be 0. **Examples** ``` DM_PROPERTY_F64(rmtp_MyValue, 0, PROFILE_PROPERTY_FRAME_RESET, "a value", &rmtp_MyGroup); ``` ### DM_PROPERTY_GROUP *Type:* MACRO Declare a property group **Parameters** - `name` (symbol) - The group name - `desc` (const char*) - The description - `parent` (ProfileIdx*) - pointer to parent property **Examples** ``` DM_PROPERTY_GROUP(rmtp_GameObject, "My Group", 0); ``` ### DM_PROPERTY_RESET *Type:* MACRO Reset a property to its default value **Parameters** - `name` (symbol) - The property **Examples** ``` DM_PROPERTY_RESET(rmtp_MyValue); ``` ### DM_PROPERTY_S32 *Type:* MACRO Declare a property of type int32_t **Parameters** - `name` (symbol) - The property symbol/name - `default` (int32_t) - The default value - `flags` (uint32_t) - The flags. Either PROFILE_PROPERTY_NONE or PROFILE_PROPERTY_FRAME_RESET. PROFILE_PROPERTY_FRAME_RESET makes the value reset each frame. - `desc` (const char*) - The description - `group` (ProfileIdx*) - The parent group. May be 0. **Examples** ``` DM_PROPERTY_S32(rmtp_MyValue, 0, PROFILE_PROPERTY_FRAME_RESET, "a value", &rmtp_MyGroup); ``` ### DM_PROPERTY_S64 *Type:* MACRO Declare a property of type int64_t **Parameters** - `name` (symbol) - The property symbol/name - `default` (int64_t) - The default value - `flags` (uint32_t) - The flags. Either PROFILE_PROPERTY_NONE or PROFILE_PROPERTY_FRAME_RESET. PROFILE_PROPERTY_FRAME_RESET makes the value reset each frame. - `desc` (const char*) - The description - `group` (ProfileIdx*) - The parent group. May be 0. **Examples** ``` DM_PROPERTY_S64(rmtp_MyValue, 0, PROFILE_PROPERTY_FRAME_RESET, "a value", &rmtp_MyGroup); ``` ### DM_PROPERTY_SET_BOOL *Type:* MACRO Set the value of a bool property **Parameters** - `name` (symbol) - The property - `value` (bool) - The value **Examples** ``` DM_PROPERTY_SET_BOOL(rmtp_MyBool, false); ``` ### DM_PROPERTY_SET_F32 *Type:* MACRO Set the value of a float property **Parameters** - `name` (symbol) - The property - `value` (float) - The value **Examples** ``` DM_PROPERTY_SET_F32(rmtp_MyValue, 1.5); ``` ### DM_PROPERTY_SET_F64 *Type:* MACRO Set the value of a double property **Parameters** - `name` (symbol) - The property - `value` (double) - The value **Examples** ``` DM_PROPERTY_SET_F64(rmtp_MyValue, 1.5); ``` ### DM_PROPERTY_SET_S32 *Type:* MACRO Set the value of a int32_t property **Parameters** - `name` (symbol) - The property - `value` (int32_t) - The value **Examples** ``` DM_PROPERTY_SET_S32(rmtp_MyValue, -1); ``` ### DM_PROPERTY_SET_S64 *Type:* MACRO Set the value of a int64_t property **Parameters** - `name` (symbol) - The property - `value` (int64_t) - The value **Examples** ``` DM_PROPERTY_SET_S64(rmtp_MyValue, -1); ``` ### DM_PROPERTY_SET_U32 *Type:* MACRO Set the value of a uint32_t property **Parameters** - `name` (symbol) - The property - `value` (uint32_t) - The value **Examples** ``` DM_PROPERTY_SET_U32(rmtp_MyValue, 1); ``` ### DM_PROPERTY_SET_U64 *Type:* MACRO Set the value of a uint64_t property **Parameters** - `name` (symbol) - The property - `value` (uint64_t) - The value **Examples** ``` DM_PROPERTY_SET_U64(rmtp_MyValue, 1); ``` ### DM_PROPERTY_U32 *Type:* MACRO Declare a property of type uint32_t **Parameters** - `name` (symbol) - The property symbol/name - `default` (uint32_t) - The default value - `flags` (uint32_t) - The flags. Either PROFILE_PROPERTY_NONE or PROFILE_PROPERTY_FRAME_RESET. PROFILE_PROPERTY_FRAME_RESET makes the value reset each frame. - `desc` (const char*) - The description - `group` (ProfileIdx*) - The parent group. May be 0. **Examples** ``` DM_PROPERTY_U32(rmtp_MyValue, 0, PROFILE_PROPERTY_FRAME_RESET, "a value", &rmtp_MyGroup); ``` ### DM_PROPERTY_U64 *Type:* MACRO Declare a property of type uint64_t **Parameters** - `name` (symbol) - The property symbol/name - `default` (uint64_t) - The default value - `flags` (uint32_t) - The flags. Either PROFILE_PROPERTY_NONE or PROFILE_PROPERTY_FRAME_RESET. PROFILE_PROPERTY_FRAME_RESET makes the value reset each frame. - `desc` (const char*) - The description - `group` (ProfileIdx*) - The parent group. May be 0. **Examples** ``` DM_PROPERTY_U64(rmtp_MyValue, 0, PROFILE_PROPERTY_FRAME_RESET, "a value", &rmtp_MyGroup); ``` ### HProfile *Type:* TYPEDEF Handle to a an active profile frame ### PROFILE_PROPERTY_INVALID_IDX *Type:* ENUM Index constant to mark a a property as invalid ### ProfileFinalize *Type:* FUNCTION Finalize the profiling system ### ProfileFrameBegin *Type:* FUNCTION Begin profiling, eg start of frame **Notes** - NULL is returned if profiling is disabled **Returns** - `context` (HProfile) - The current profiling context. Must be released by #EndFrame ### ProfileFrameEnd *Type:* FUNCTION Release profile returned by #ProfileFrameBegin **Parameters** - `profile` (HProfile) - Profile to release **Returns** - `result` (ProfileResult) - Status for the frame end operation ### ProfileIdx *Type:* TYPEDEF Index type to hold internal references of samplers and properties ### ProfileInitialize *Type:* FUNCTION Initialize the profiling system ### ProfileIsInitialized *Type:* FUNCTION Finalize the profiling system **Returns** - `initialized` (bool) - Returns non zero if the profiler is initialized ### ProfileListener *Type:* STRUCT Structure for registering a profile listener ### ProfileLogText *Type:* FUNCTION Log text via the registered profilers **Parameters** - `name` (const char*) - Name of the scope - `...` (va_list) - Arguments for internal logging function **Returns** - `result` (ProfileResult) - Status for the log text operation ### ProfilePropertyFlags *Type:* ENUM Set of bit flags to be used when declaring propertis **Members** - `PROFILE_PROPERTY_NONE` - `PROFILE_PROPERTY_FRAME_RESET` ### ProfilePropertyType *Type:* ENUM Enum to describe type of a property **Members** - `PROFILE_PROPERTY_TYPE_GROUP` - `PROFILE_PROPERTY_TYPE_BOOL` - `PROFILE_PROPERTY_TYPE_S32` - `PROFILE_PROPERTY_TYPE_U32` - `PROFILE_PROPERTY_TYPE_F32` - `PROFILE_PROPERTY_TYPE_S64` - `PROFILE_PROPERTY_TYPE_U64` - `PROFILE_PROPERTY_TYPE_F64` ### ProfilePropertyValue *Type:* FUNCTION Union to hold a property value ### ProfileRegisterProfiler *Type:* FUNCTION Register a new profiler. Can be done after the profiling has started. **Parameters** - `name` (const char*) - Name of the profiler ### ProfileResult *Type:* ENUM Enum to describe the result of a profiler operation **Members** - `PROFILE_RESULT_OK` - `PROFILE_RESULT_NOT_INITIALIZED` - `PROFILE_RESULT_OUT_OF_SAMPLES` ### ProfileScopeBegin *Type:* FUNCTION Start a new profile scope **Parameters** - `name` (const char*) - Name of the scope - `name_hash` (uint64_t) - Hashed name of the scope **Returns** - `result` (ProfileResult) - Status for the scope begin operation ### ProfileScopeEnd *Type:* FUNCTION End the last added scope **Parameters** - `name` (const char*) - Name of the scope - `name_hash` (uint64_t) - Hashed name of the scope **Returns** - `result` (ProfileResult) - Status for the scope end operation ### ProfileSetThreadName *Type:* FUNCTION Set the current thread name to each registered profiler **Parameters** - `name` (const char*) - Name of the thread **Returns** - `result` (ProfileResult) - Status for the thread name operation ### ProfileUnregisterProfiler *Type:* FUNCTION Unregister a profiler **Parameters** - `name` (const char*) - Name of the profiler # Shared Library {#apis:engine-dlib-src-dmsdk-dlib-shared_library-h} **Namespace:** `SharedLibrary` **Language:** C++ **Type:** Defold C++ **File:** `shared_library.h` **Source:** `engine/dlib/src/dmsdk/dlib/shared_library.h` **Include:** `dmsdk/dlib/shared_library.h` Utility functions for shared library export/import ## API ### DM_DLLEXPORT *Type:* MACRO Export and import functions, data, and objects to or from a DLL **Examples** ``` DM_DLLEXPORT uint64_t dmHashBuffer64(const void* buffer, uint32_t buffer_len); ``` # Socket {#apis:engine-dlib-src-dmsdk-dlib-socket-h} **Namespace:** `dmSocket` **Language:** C++ **Type:** Defold C++ **File:** `socket.h` **Source:** `engine/dlib/src/dmsdk/dlib/socket.h` **Include:** `dmsdk/dlib/socket.h` Socket functions. ## API ### Address *Type:* STRUCT Network addresses were previously represented as an uint32_t, but in order to support IPv6 the internal representation was changed to a struct. ### Connect *Type:* FUNCTION Initiate a connection on a socket **Parameters** - `socket` (Socket) - Socket to initiate connection on - `address` (Address) - Address to connect to - `port` (int) - Port to connect to **Returns** - `return` (Result) - RESULT_OK on success ### Delete *Type:* FUNCTION Delete a socket. Corresponds to BSD socket function close() **Parameters** - `socket` (Socket) - Socket to close **Returns** - `return` (Result) - RESULT_OK on success ### Domain *Type:* ENUM Domain type **Members** - `DOMAIN_MISSING` - `DOMAIN_IPV4` - `DOMAIN_IPV6` - `DOMAIN_UNKNOWN` ### GetFD *Type:* FUNCTION Get underlying file descriptor **Parameters** - `socket` (Socket) - socket to get fd for **Returns** - `return` (int) - file-descriptor ### GetHostByName *Type:* FUNCTION Get host by name **Parameters** - `name` (const char*) - Hostname to resolve - `address` (Address*) - Host address result - `ipv4` (bool) - Whether or not to search for IPv4 addresses - `ipv6` (bool) - Whether or not to search for IPv6 addresses **Returns** - `return` (Result) - RESULT_OK on success ### GetHostByName *Type:* FUNCTION Get host by name with timeout and cancelability **Notes** - On HTML5, this function is a wrapper for dmSocket::GetHostByName **Parameters** - `name` (const char*) - Hostname to resolve - `address` (Address*) - Host address result - `timeout` (uint64_t) - Timeout in microseconds - `cancelflag` (int*) - if non null and set, will abort the call - `ipv4` (bool) - Whether or not to search for IPv4 addresses - `ipv6` (bool) - Whether or not to search for IPv6 addresses **Returns** - `return` (Result) - RESULT_OK on success ### INVALID_SOCKET_HANDLE *Type:* CONSTANT Invalid socket handle ### New *Type:* FUNCTION Create a new socket. Corresponds to BSD socket function socket(). **Notes** - SIGPIPE is disabled on applicable platforms. This has the implication that Receive can return zero bytes when the connection is closed by remote peer. **Parameters** - `type` (Type) - Socket type - `protocol` (Protocol) - Protocol - `socket` (Socket*) - Pointer to socket **Returns** - `return` (Result) - RESULT_OK on succcess ### Protocol *Type:* ENUM Network protocol **Members** - `PROTOCOL_TCP` - `PROTOCOL_UDP` ### Receive *Type:* FUNCTION Receive data on a socket **Notes** - For dmSocket::Recv() and dmSocket::Send() function ETIMEDOUT is translated to EWOULDBLOCK on win32 for compatibility with BSD sockets. **Parameters** - `socket` (Socket) - Socket to receive data on - `buffer[out]` (void*) - Buffer to receive to - `length` (int) - Receive buffer length - `received_bytes[out]` (int*) - Number of received bytes (result) **Returns** - `return` (Result) - RESULT_OK on success ### Result *Type:* ENUM Socket result **Members** - `RESULT_OK` - 0 - `RESULT_ACCES` - -1 - `RESULT_AFNOSUPPORT` - -2 - `RESULT_WOULDBLOCK` - -3 - `RESULT_BADF` - -4 - `RESULT_CONNRESET` - -5 - `RESULT_DESTADDRREQ` - -6 - `RESULT_FAULT` - -7 - `RESULT_HOSTUNREACH` - -8 - `RESULT_INTR` - -9 - `RESULT_INVAL` - -10 - `RESULT_ISCONN` - -11 - `RESULT_MFILE` - -12 - `RESULT_MSGSIZE` - -13 - `RESULT_NETDOWN` - -14 - `RESULT_NETUNREACH` - -15 - `RESULT_NOBUFS` - -17 - `RESULT_NOTCONN` - -20 - `RESULT_NOTSOCK` - -22 - `RESULT_OPNOTSUPP` - -23 - `RESULT_PIPE` - -24 - `RESULT_PROTONOSUPPORT` - -25 - `RESULT_PROTOTYPE` - -26 - `RESULT_TIMEDOUT` - -27 - `RESULT_ADDRNOTAVAIL` - -28 - `RESULT_CONNREFUSED` - -29 - `RESULT_ADDRINUSE` - -30 - `RESULT_CONNABORTED` - -31 - `RESULT_INPROGRESS` - -32 - `RESULT_HOST_NOT_FOUND` - -100 - `RESULT_TRY_AGAIN` - -101 - `RESULT_NO_RECOVERY` - -102 - `RESULT_NO_DATA` - -103 - `RESULT_UNKNOWN` - -1000 ### ResultToString *Type:* FUNCTION Convert result value to string **Parameters** - `result` (Result) - Result to convert **Returns** - `return` (const char*) - Result as string ### Select *Type:* FUNCTION Select for pending data **Parameters** - `selector` (Selector*) - Selector - `timeout` (int) - Timeout. For blocking pass -1. (microseconds) **Returns** - `return` (Result) - RESULT_OK on success ### Selector *Type:* STRUCT Selector ### SelectorClear *Type:* FUNCTION Clear selector for socket. Similar to FD_CLR **Parameters** - `selector` (Selector*) - Selector - `selector_kind` (SelectorKind) - Kind to clear - `socket` (Socket) - Socket to clear **Returns** - `return` (void) ### SelectorIsSet *Type:* FUNCTION Check if selector is set. Similar to FD_ISSET **Parameters** - `selector` (Selector*) - Selector - `selector_kind` (SelectorKind) - Selector kind - `socket` (Socket) - Socket to check for **Returns** - `return` (bool) - True if set. ### SelectorKind *Type:* ENUM Selector kind **Members** - `SELECTOR_KIND_READ` - `SELECTOR_KIND_WRITE` - `SELECTOR_KIND_EXCEPT` ### SelectorSet *Type:* FUNCTION Set selector for socket. Similar to FD_SET **Parameters** - `selector` (Selector*) - Selector - `selector_kind` (SelectorKind) - Kind to clear - `socket` (Socket) - Socket to set **Returns** - `return` (void) ### SelectorZero *Type:* FUNCTION Clear selector (all kinds). Similar to FD_ZERO **Parameters** - `selector` (Selector*) - Selector **Returns** - `return` (void) ### Send *Type:* FUNCTION Send a message on a socket **Notes** - For dmSocket::Recv() and dmSocket::Send() function ETIMEDOUT is translated to EWOULDBLOCK on win32 for compatibility with BSD sockets. **Parameters** - `socket` (Socket) - Socket to send a message on - `buffer` (void*) - Buffer to send - `length` (int) - Length of buffer to send - `sent_bytes[out]` (int*) - Number of bytes sent (result) **Returns** - `return` (Result) - RESULT_OK on success ### SetBlocking *Type:* FUNCTION Set blocking option on a socket **Parameters** - `socket` (Socket) - Socket to set blocking on - `blocking` (bool) - True to block **Returns** - `return` (Result) - RESULT_OK on success ### SetBroadcast *Type:* FUNCTION Set broadcast address option on socket. Socket option SO_BROADCAST on most platforms. **Parameters** - `socket` (Socket) - Socket to set reuse address to - `broadcast` (bool) - True if broadcast **Returns** - `return` (Result) - RESULT_OK on success ### SetNoDelay *Type:* FUNCTION Set TCP_NODELAY on socket **Parameters** - `socket` (Socket) - Socket to set TCP_NODELAY on - `no_delay` (bool) - True for no delay **Returns** - `return` (Result) - RESULT_OK on success ### SetQuickAck *Type:* FUNCTION Set TCP_QUICKACK on socket **Notes** - This is a no op on platforms that doesn't support it **Parameters** - `socket` (Socket) - Socket to set TCP_QUICKACK on - `use_quick_ack` (bool) - False to disable quick ack **Returns** - `return` (Result) - RESULT_OK on success ### SetReceiveTimeout *Type:* FUNCTION Set socket receive timeout **Notes** - Timeout resolution might be in milliseconds, e.g. windows. Use values larger than or equal to 1000 **Parameters** - `socket` (Socket) - socket - `timeout` (uint64_t) - timeout in microseconds **Returns** - `return` (Result) - RESULT_OK on success ### SetReuseAddress *Type:* FUNCTION Set reuse socket address option on socket. Socket option SO_REUSEADDR on most platforms **Parameters** - `socket` (Socket) - Socket to set reuse address to - `reuse` (bool) - True if reuse **Returns** - `return` (Result) - RESULT_OK on success ### SetSendTimeout *Type:* FUNCTION Set socket send timeout **Notes** - Timeout resolution might be in milliseconds, e.g. windows. Use values larger than or equal to 1000. **Parameters** - `socket` (Socket) - socket - `timeout` (uint64_t) - timeout in microseconds **Returns** - `return` (Result) - RESULT_OK on success ### Shutdown *Type:* FUNCTION Shutdown part of a socket connection **Parameters** - `socket` (Socket) - Socket to shutdown connection ow - `how` (ShutdownType) - Shutdown type **Returns** - `return` (Result) - RESULT_OK on success ### ShutdownType *Type:* ENUM Socket shutdown type **Members** - `SHUTDOWNTYPE_READ` - `SHUTDOWNTYPE_WRITE` - `SHUTDOWNTYPE_READWRITE` ### Socket *Type:* TYPEDEF Socket type definition **Notes** - Use dmSocket::INVALID_SOCKET_HANDLE instead of zero for unset values. This is an exception from all other handles. ### SOCKET_TIMEOUT *Type:* CONSTANT Socket default timeout value ### Type *Type:* ENUM Socket type **Members** - `TYPE_STREAM` - `TYPE_DGRAM` # Spinlock {#apis:engine-dlib-src-dmsdk-dlib-spinlock-h} **Namespace:** `dmSpinlock` **Language:** C++ **Type:** Defold C++ **File:** `spinlock.h` **Source:** `engine/dlib/src/dmsdk/dlib/spinlock.h` **Include:** `dmsdk/dlib/spinlock.h` API for platform independent spinlock synchronization primitive. ## API ### DM_SPINLOCK_SCOPED_LOCK *Type:* MACRO Will lock a Spinlock and automatically unlock it at the end of the scope. **Parameters** - `mutex` (dmSpinlock::Spinlock) - Spinlock reference to lock. ### dmSpinlock::Init *Type:* FUNCTION Initialize a Spinlock **Parameters** - `spinlock` (dmSpinlock::Spinlock*) - spinlock to initialize. ### dmSpinlock::Lock *Type:* FUNCTION Lock a Spinlock **Parameters** - `spinlock` (dmSpinlock::Spinlock*) - spinlock to lock. ### dmSpinlock::Spinlock *Type:* TYPEDEF ``` typedef Spinlock; ``` ### dmSpinlock::Unlock *Type:* FUNCTION Unlock a Spinlock **Parameters** - `spinlock` (dmSpinlock::Spinlock*) - spinlock to unlock. # SSLSocket {#apis:engine-dlib-src-dmsdk-dlib-sslsocket-h} **Namespace:** `dmSSLSocket` **Language:** C++ **Type:** Defold C++ **File:** `sslsocket.h` **Source:** `engine/dlib/src/dmsdk/dlib/sslsocket.h` **Include:** `dmsdk/dlib/sslsocket.h` Secure socket functions. ## API ### Delete *Type:* FUNCTION Delete a secure socket. Does not close the underlying socket **Parameters** - `socket` (Socket) - Secure socket to close **Returns** - `result` (Result) - RESULT_OK on success **Examples** ``` dmSSLSocket::Delete(sslsocket); ``` ### dmSocket::SetReceiveTimeout *Type:* FUNCTION Set socket receive timeout **Notes** - Timeout resolution might be in milliseconds, e.g. windows. Use values larger than or equal to 1000 **Parameters** - `socket` (Socket) - socket - `timeout` (uint64_t) - timeout in microseconds **Returns** - `result` (dmSocket::Result) - RESULT_OK on success ### INVALID_SOCKET_HANDLE *Type:* CONSTANT SSLSocket socket handle ### New *Type:* FUNCTION Create a new secure socket **Parameters** - `socket` (dmSocket::Socket) - The socket to wrap - `host` (const char*) - The name of the host (e.g. "httpbin.org") - `timeout` (uint64_t) - The timeout for the handshake procedure. (microseconds) - `sslsocket` (Socket*) - Pointer to a secure socket **Returns** - `result` (Result) - RESULT_OK on success **Examples** ``` dmSSLSocket::Result result; dmSSLSocket::Socket sslsocket; result = dmSSLSocket::New(socket, "httpbin.org", 500*1000, &sslsocket); if (dmSSLSocket::RESULT_OK == result) { // ... } else { // ... } ``` ### Receive *Type:* FUNCTION Receive data on a secure socket **Parameters** - `socket` (Socket) - Socket to receive data on - `buffer` (void*) - Buffer to receive to - `length` (int) - Receive buffer length - `received_bytes` (int*) - Number of received bytes (result) **Returns** - `result` (dmSocket::Result) - RESULT_OK on success ### Result *Type:* ENUM Result enumeration. **Members** - `dmSSLSocket::RESULT_OK` - (0) - `dmSSLSocket::RESULT_SSL_INIT_FAILED` - (-2000) - `dmSSLSocket::RESULT_HANDSHAKE_FAILED` - (-2001) - `dmSSLSocket::RESULT_WOULDBLOCK` - (-2002) - `dmSSLSocket::RESULT_CONNREFUSED` - (-2003) ### Send *Type:* FUNCTION Send a message on a secure socket **Parameters** - `socket` (Socket) - SSL socket to send a message on - `buffer` (void*) - Buffer to send - `length` (int) - Length of buffer to send - `sent_bytes` (int*) - Number of bytes sent (result) **Returns** - `result` (dmSocket::Result) - RESULT_OK on success ### Socket *Type:* TYPEDEF Socket type definition # Static Assert {#apis:engine-dlib-src-dmsdk-dlib-static_assert-h} **Namespace:** `dmStaticAssert` **Language:** C++ **Type:** Defold C++ **File:** `static_assert.h` **Source:** `engine/dlib/src/dmsdk/dlib/static_assert.h` **Include:** `dmsdk/dlib/static_assert.h` ```cpp void test() { DM_STATIC_ASSERT(sizeof(int) == 4, Invalid_int_size); } ``` ## API ### DM_STATIC_ASSERT *Type:* MACRO This is using C++11 static_assert on platforms that support it and use c++11. Otherwise it's using a c construct to check the condition. As such, it is currently required to be used whithin a function scope. **Parameters** - `x` (bool) - expression - `xmsg` (string) - expression **Examples** Verify the size of a struct is within a limit ``` DM_STATIC_ASSERT(sizeof(MyStruct) <= 32, Invalid_Struct_Size); ``` # Sys {#apis:engine-dlib-src-dmsdk-dlib-sys-h} **Namespace:** `dmSys` **Language:** C++ **Type:** Defold C++ **File:** `sys.h` **Source:** `engine/dlib/src/dmsdk/dlib/sys.h` **Include:** `dmsdk/dlib/sys.h` Sys allocation functions ## API ### Exists *Type:* FUNCTION Checks if a path exists **Parameters** - `path` (const char*) - path to directory to create **Returns** - `result` (bool) - true on success ### Rename *Type:* FUNCTION Move a file or directory **Notes** - This operation is atomic **Parameters** - `dst_path` (const char*) - the destination path. The file which contents is to be overwritten. - `src_path` (const char*) - the source path. The contents will be written to the destination path and the file unlinked if successful. **Returns** - `RESULT_OK` - on success ### Result *Type:* ENUM Result code. Similar to standard posix result codes **Members** - `dmSys::RESULT_OK` - 0 - `dmSys::RESULT_PERM` - -1 - `dmSys::RESULT_NOENT` - -2 - `dmSys::RESULT_SRCH` - -3 - `dmSys::RESULT_INTR` - -4 - `dmSys::RESULT_IO` - -5 - `dmSys::RESULT_NXIO` - -6 - `dmSys::RESULT_2BIG` - -7 - `dmSys::RESULT_NOEXEC` - -8 - `dmSys::RESULT_BADF` - -9 - `dmSys::RESULT_CHILD` - -10 - `dmSys::RESULT_DEADLK` - -11 - `dmSys::RESULT_NOMEM` - -12 - `dmSys::RESULT_ACCES` - -13 - `dmSys::RESULT_FAULT` - -14 - `dmSys::RESULT_BUSY` - -15 - `dmSys::RESULT_EXIST` - -16 - `dmSys::RESULT_XDEV` - -17 - `dmSys::RESULT_NODEV` - -18 - `dmSys::RESULT_NOTDIR` - -19 - `dmSys::RESULT_ISDIR` - -20 - `dmSys::RESULT_INVAL` - -21 - `dmSys::RESULT_NFILE` - -22 - `dmSys::RESULT_MFILE` - -23 - `dmSys::RESULT_NOTTY` - -24 - `dmSys::RESULT_TXTBSY` - -25 - `dmSys::RESULT_FBIG` - -26 - `dmSys::RESULT_NOSPC` - -27 - `dmSys::RESULT_SPIPE` - -28 - `dmSys::RESULT_ROFS` - -29 - `dmSys::RESULT_MLINK` - -30 - `dmSys::RESULT_PIPE` - -31 - `dmSys::RESULT_NOTEMPTY` - -32 - `dmSys::RESULT_UNKNOWN` - -1000 ### StatInfo *Type:* STRUCT Status info for a file or directory **Members** - `m_Size` (uint32_t) - the file size (if it's a file) - `m_Mode` (uint32_t) - the flags of the path - `m_AccessTime` (uint32_t) - the last access time - `m_ModifiedTime` (uint32_t) - the last modified time ### Unlink *Type:* FUNCTION Remove file **Parameters** - `path` (const char*) - path to file to remove **Returns** - `result` (dmSys::Result) - RESULT_OK on success # Thread {#apis:engine-dlib-src-dmsdk-dlib-thread-h} **Namespace:** `dmThread` **Language:** C++ **Type:** Defold C++ **File:** `thread.h` **Source:** `engine/dlib/src/dmsdk/dlib/thread.h` **Include:** `dmsdk/dlib/thread.h` Thread functions. ## API ### AllocTls *Type:* FUNCTION Allocate thread local storage key **Returns** - `key` (dmThread::TlsKey) - Key ### Detach *Type:* FUNCTION Detach thread. When a detached thread terminates, its resources are automatically released back to the system without the need for another thread to join with the terminated thread. **Parameters** - `thread` (dmThread::Thread) - Thread to detach ### FreeTls *Type:* FUNCTION Free thread local storage key **Parameters** - `key` (dmThread::TlsKey) - Key ### GetCurrentThread *Type:* FUNCTION Gets the current thread **Returns** - `thread` (dmThread::Thread) - the current thread ### GetTlsValue *Type:* FUNCTION Get thread specific data **Parameters** - `key` (dmThread::TlsKey) - Key ### Join *Type:* FUNCTION Join thread. Waits for the thread specified by thread to terminate. If that thread has already terminated, then Join() returns immediately. The thread specified by thread must be joinable (see Detach()). **Parameters** - `thread` (dmThread::Thread) - Thread to join ### New *Type:* FUNCTION Create a new named thread **Notes** - thread name currently not supported on win32 **Parameters** - `thread_start` (ThreadStart) - Thread entry function - `stack_size` (uint32_t) - Stack size - `arg` (void*) - Thread argument - `name` (const char*) - Thread name **Returns** - `thread` (dmThread::Thread) - Thread handle **Examples** Create a thread ``` #include #include struct Context { bool m_DoWork; int m_Work; }; static void Worker(void* _ctx) { Context* ctx = (Context*)_ctx; while (ctx->m_DoWork) { ctx->m_Work++; // do work dmTime::Sleep(10*1000); // yield } } int StartThread() { Context ctx; ctx.m_DoWork = true; ctx.m_Work = 0; dmThread::Thread thread = dmThread::New(Worker, 0x80000, (void*)&ctx, "my_thread"); // do other work... // ..eventually stop the thread: ctx.m_DoWork = false; // wait for thread dmThread::Join(thread); printf("work done: %d\n", ctx.m_Work); } ``` ### SetThreadName *Type:* FUNCTION Sets the current thread name **Notes** - The thread argument is unused on Darwin (uses current thread) **Parameters** - `thread` (dmThread::Thread) - the thread - `name` (const char*) - the thread name ### SetTlsValue *Type:* FUNCTION Set thread specific data **Parameters** - `key` (dmThread::TlsKey) - Key - `value` (void*) - Value ### ThreadStart *Type:* TYPEDEF # Time {#apis:engine-dlib-src-dmsdk-dlib-time-h} **Namespace:** `dmTime` **Language:** C++ **Type:** Defold C++ **File:** `time.h` **Source:** `engine/dlib/src/dmsdk/dlib/time.h` **Include:** `dmsdk/dlib/time.h` Time functions. ## API ### dmTime::GetMonotonicTime *Type:* FUNCTION Get monotonic time in microseconds since some unspecified starting point. **Returns** - `result` (uint64_t) - Monotonic time in microseconds ### dmTime::GetTime *Type:* FUNCTION Get current time in microseconds since Jan. 1, 1970. **Returns** - `result` (uint64_t) - Current time in microseconds ### dmTime::Sleep *Type:* FUNCTION Sleep thread with low precision (~10 milliseconds). **Parameters** - `useconds` (uint32_t) - Time to sleep in microseconds # Transform {#apis:engine-dlib-src-dmsdk-dlib-transform-h} **Namespace:** `dmTransform` **Language:** C++ **Type:** Defold C++ **File:** `transform.h` **Source:** `engine/dlib/src/dmsdk/dlib/transform.h` **Include:** `dmsdk/dlib/transform.h` Api for transforms with rotation, scale and translation ## API ### Apply *Type:* FUNCTION Apply the transform on a point (includes the transform translation). **Parameters** - `t` (dmTransform::Transform&) - Transform - `p` (dmVMath::Point3&) - Point **Returns** - `point` (dmVMath::Point3) - Transformed point ### Apply *Type:* FUNCTION Apply the transform on a vector (excludes the transform translation). **Parameters** - `t` (dmTransform::Transform&) - Transform - `v` (dmVMath::Vector3&) - Vector **Returns** - `point` (dmVMath::Vector3) - Transformed vector ### ExtractScale *Type:* FUNCTION Extract the absolute values of the scale component from a matrix. **Parameters** - `mtx` (dmVMath::Matrix4) - Source matrix **Returns** - `Vector3` - with scale values for x,y,z ### GetRotation *Type:* FUNCTION get rotatiom **Returns** - `rotation` (dmVMath::Quat) ### GetScale *Type:* FUNCTION get scale **Returns** - `scale` (dmVMath::Vector3) ### GetTranslation *Type:* FUNCTION get translation **Returns** - `translation` (dmVMath::Vector3) ### GetUniformScale *Type:* FUNCTION Compute a 'uniform' scale for this transform. In the event that the scale applied to this transform is not uniform then the value is arbitrary: we make a selection that will not introduce any floating point rounding errors. **Returns** - `scale` (float) - the uniform scale associated with this transform. ### Inv *Type:* FUNCTION Invert a transform **Parameters** - `t` (const dmTransform::Transform&) **Returns** - `result` (dmTransform::Transform) - inverted transform ### Mul *Type:* FUNCTION Transforms the right-hand transform by the left-hand transform **Parameters** - `lhs` (const dmTransform::Transform&) - `rhs` (const dmTransform::Transform&) **Returns** - `result` (dmTransform::Transform) - Transformed transform ### NormalizeZScale *Type:* FUNCTION Eliminate the z scaling components in a matrix **Parameters** - `mtx` (dmVMath::Matrix4) - Matrix to operate on ### NormalizeZScale *Type:* FUNCTION Eliminate the z scaling components in a matrix **Parameters** - `source` (const dmVMath::Matrix&) - Source matrix - `target` (dmVMath::Matrix*) - Target matrix ### ResetScale *Type:* FUNCTION Eliminate the scaling components in a matrix **Parameters** - `mtx` (dmVMath::Matrix4) - Matrix to operate on **Returns** - `Vector` - containing the scaling by component ### SetIdentity *Type:* FUNCTION initialize to identity transform ### SetRotation *Type:* FUNCTION set rotatiom **Parameters** - `rotation` (dmVMath::Quat) ### SetScale *Type:* FUNCTION set scale **Returns** - `scale` (dmVMath::Vector3) ### SetScaleXY *Type:* FUNCTION set scale for x and y **Parameters** - `scale_x` (float) - `scale_y` (float) ### SetTranslation *Type:* FUNCTION set translation **Parameters** - `translation` (dmVMath::Vector3) ### SetUniformScale *Type:* FUNCTION set uniform scale **Parameters** - `scale` (float) ### ToMatrix4 *Type:* FUNCTION Convert a transform into a 4-dim matrix **Parameters** - `t` (Transform) - Transform to convert **Returns** - `Matrix` - representing the same transform ### ToTransform *Type:* FUNCTION Convert a matrix into a transform **Parameters** - `mtx` (dmVMath::Matrix4) - Matrix4 to convert **Returns** - `Transform` - representing the same transform ### Transform *Type:* STRUCT Transform with non-uniform (3-component) scale. Transform applied as: T(p) = translate(rotate(scale(p))) = p' The scale is non-rotated to avoid shearing in the transform. Two transforms are applied as: T1(T2(p)) = t1(r1(t2(r2(s1(s2(p)))))) = p' This means that the transform is not associative: T1(T2(p)) != (T1*T2)(P) ### Transform *Type:* FUNCTION Constructor. Leaves the struct in an uninitialized state ### Transform *Type:* FUNCTION constructor **Parameters** - `translation` (dmVMath::Vector3) - `rotation` (dmVMath::Quat) - `scale` (dmVMath::Vector3) ### Transform *Type:* FUNCTION constructor **Parameters** - `translation` (dmVMath::Vector3) - `rotation` (dmVMath::Quat) - `scale` (dmVMath::Vector3) # URI {#apis:engine-dlib-src-dmsdk-dlib-uri-h} **Namespace:** `dmURI` **Language:** C++ **Type:** Defold C++ **File:** `uri.h` **Source:** `engine/dlib/src/dmsdk/dlib/uri.h` **Include:** `dmsdk/dlib/uri.h` URI functions. ## API ### dmURI::Decode *Type:* FUNCTION Decodes an URL encoded buffer **Notes** - The output will never be larger than the input. **Parameters** - `src` (const char*) - Input - `dst` (char*) - Decoded output ### dmURI::Encode *Type:* FUNCTION Performs URL encoding of the supplied buffer **Notes** - If dst=0 the bytes_written will return the number of required bytes (including null character) **Parameters** - `src` (const char*) - string to encode - `dst` (char*) - the destination buffer - `dst_size` (uint32_t) - size of the provided out buffer - `bytes_written[out]` (uint32_t) - number of bytes written ### dmURI::Parse *Type:* FUNCTION Parse URI and split in three parts. (scheme, location, path) **Notes** - This is a simplified URI parser and does not conform to rfc2396. Missing features are: parameters, query, fragment part of URI and support for escaped sequences - For http m_Port is set to 80 if not specified in uri. **Parameters** - `uri` (const char*) - URI to parse - `parts` (dmURI::Parts) - Result **Returns** - `RESULT_OK` - on success ### dmURI::Parts *Type:* STRUCT URI parsing result parts ### dmURI::Result *Type:* FUNCTION URI parsing result # Utf8 {#apis:engine-dlib-src-dmsdk-dlib-utf8-h} **Namespace:** `dmUtf8` **Language:** C++ **Type:** Defold C++ **File:** `utf8.h` **Source:** `engine/dlib/src/dmsdk/dlib/utf8.h` **Include:** `dmsdk/dlib/utf8.h` Utf8 API documentation ## API ### IsBreaking *Type:* FUNCTION Checks if a codepoint is a breaking whitespace **Parameters** - `c` (uint32_t) - the codepoint **Returns** - `result` (bool) - true if it's a breaking whitespace ### IsWhiteSpace *Type:* FUNCTION Checks if a codepoint is a whitespace **Parameters** - `c` (uint32_t) - the codepoint **Returns** - `result` (bool) - true if it's a whitespace ### NextChar *Type:* FUNCTION Get next unicode character in utf-8 string. Iteration terminates at '\0' and repeated invocations will return '\0' **Parameters** - `str` (const char**) - Pointer to string. The pointer value is updated **Returns** - `chr` (uint32_t) - Decoded unicode character **Examples** ``` const char* s = "åäöÅÄÖ"; char* cursor = s; uint32_t codepoint = 0; while (codepoint = dmUtf8::NextChar(&cursor)) { // ... } ``` ### StrLen *Type:* FUNCTION Get number of unicode characters in utf-8 string **Parameters** - `str` (const char*) - Utf8 string **Returns** - `length` (uint32_t) - Number of characters **Examples** ``` const char* s = "åäöÅÄÖ"; uint32_t count = dmUtf8::StrLen(s); ``` ### ToUtf8 *Type:* FUNCTION Convert a 16-bit unicode character to utf-8 **Notes** - Buffer must be of at least 4 characters. The string is *not* NULL-terminated **Parameters** - `chr` (uint16_t) - Character to convert - `buf` (char*) - output Buffer (at least 4 bytes) **Returns** - `length` (uint32_t) - Number of characters in buffer # Vector Math {#apis:engine-dlib-src-dmsdk-dlib-vmath-h} **Namespace:** `dmVMath` **Language:** C++ **Type:** Defold C++ **File:** `vmath.h` **Source:** `engine/dlib/src/dmsdk/dlib/vmath.h` **Include:** `dmsdk/dlib/vmath.h` Vector Math functions. ## API ### AppendScale *Type:* FUNCTION post multiply scale **Parameters** - `m` (Matrix4) - the matrix - `v` (Vector3) - the scale vector **Returns** - `r` (Matrix4) - the scaled vector ### Cross *Type:* FUNCTION cross product between two vectors **Parameters** - `a` (Vector3) - the operand - `b` (Vector3) - the dividend **Returns** - `v` (Vector3) - the result vector ### DivPerElem *Type:* FUNCTION Divide two vectors per element: Vector3(a.x/b.x, a.y/b.y, a.z/b.z) **Parameters** - `a` (Vector3) - the operand - `b` (Vector3) - the dividend **Returns** - `v` (Vector3) - the result vector ### DivPerElem *Type:* FUNCTION Divide two vectors per element: Vector3(a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w) **Parameters** - `a` (Vector4) - the operand - `b` (Vector4) - the dividend **Returns** - `v` (Vector4) - the result vector ### Dot *Type:* FUNCTION dot product between two vectors **Parameters** - `a` (Vector3) - the first vector - `b` (Vector3) - the second vector **Returns** - `dot_product` (float) - the dot product ### Dot *Type:* FUNCTION dot product between two vectors **Parameters** - `a` (Vector4) - the first vector - `b` (Vector4) - the second vector **Returns** - `dot_product` (float) - the dot product ### EulerToQuat *Type:* FUNCTION Converts euler angles (x, y, z) in degrees into a quaternion The error is guaranteed to be less than 0.001. **Parameters** - `xyz` (Vector3) - rotation (deg) ### Inverse *Type:* FUNCTION inverse matrix **Parameters** - `m` (Matrix3) - the rotation **Returns** - `r` (Matrix3) - the transposed matrix ### Inverse *Type:* FUNCTION inverse matrix **Parameters** - `m` (Matrix4) - the rotation **Returns** - `r` (Matrix4) - the transposed matrix ### Length *Type:* FUNCTION calculate length of a vector **Parameters** - `v` (Vector3) - the vector **Returns** - `length` (float) - the length ### Length *Type:* FUNCTION calculate length of a vector **Parameters** - `v` (Vector3) - the vector **Returns** - `length` (float) - the length ### Length *Type:* FUNCTION calculate length of a quaternion **Parameters** - `v` (Quat) - the quaternion **Returns** - `length` (float) - the length ### Length *Type:* FUNCTION calculate squared length of a vector **Parameters** - `v` (Vector3) - the vector **Returns** - `length` (float) - the squared length ### Length *Type:* FUNCTION calculate squared length of a vector **Parameters** - `v` (Vector4) - the vector **Returns** - `length` (float) - the squared length ### Length *Type:* FUNCTION calculate squared length of a quaternion **Parameters** - `v` (Quat) - the vector **Returns** - `length` (float) - the squared length ### Lerp *Type:* FUNCTION linear interpolate between two vectors **Notes** - Does not clamp t to between 0 and 1 **Parameters** - `t` (float) - the unit time - `a` (Vector3) - the start vector (t == 0) - `b` (Vector3) - the end vector (t == 1) **Returns** - `v` (Vector3) - the result vector v = a + (b - a) * t **Examples** ``` dmVMath::Vector3 v0 = dmVMath::Lerp(0.0f, a, b); // v0 == a dmVMath::Vector3 v1 = dmVMath::Lerp(1.0f, a, b); // v1 == b dmVMath::Vector3 v2 = dmVMath::Lerp(2.0f, a, b); // v2 == a + (b-a) * 2.0f ``` ### Lerp *Type:* FUNCTION linear interpolate between two vectors **Notes** - Does not clamp t to between 0 and 1 **Parameters** - `t` (float) - the unit time - `a` (Vector4) - the start vector (t == 0) - `b` (Vector4) - the end vector (t == 1) **Returns** - `v` (Vector4) - the result vector v = a + (b - a) * t **Examples** ``` dmVMath::Vector4 v0 = dmVMath::Lerp(0.0f, a, b); // v0 == a dmVMath::Vector4 v1 = dmVMath::Lerp(1.0f, a, b); // v1 == b dmVMath::Vector4 v2 = dmVMath::Lerp(2.0f, a, b); // v2 == a + (b-a) * 2.0f ``` ### Matrix3 *Type:* TYPEDEF A 3x3 matrix **Notes** - 16 byte aligned - Implemented as 3 x Vector3 - Column major - Currently scalar implementation is used on most platforms ### Matrix4 *Type:* TYPEDEF A 4x4 matrix **Notes** - 16 byte aligned - Implemented as 4 x Vector4 - Column major - Currently scalar implementation is used on most platforms ### MulPerElem *Type:* FUNCTION Multiply two vectors per element: Vector3(a.x * b.x, a.y * b.y, a.z * b.z) **Parameters** - `a` (Vector3) - the first vector - `b` (Vector3) - the second vector **Returns** - `v` (Vector3) - the result vector ### MulPerElem *Type:* FUNCTION Multiply two vectors per element: Vector3(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w) **Parameters** - `a` (Vector4) - the first vector - `b` (Vector4) - the second vector **Returns** - `v` (Vector4) - the result vector ### MulPerElem *Type:* FUNCTION Return absolute value per element: Vector3(abs(v.x), abs(v.y), abs(v.z)) **Parameters** - `v` (Vector3) - the vector **Returns** - `r` (Vector3) - the result vector ### MulPerElem *Type:* FUNCTION Returns the conjugate of the quaternion: conj = -q **Parameters** - `q` (Quat) - the quaternions **Returns** - `r` (Quat) - the result ### Normalize *Type:* FUNCTION normalize a vector to length 1 **Parameters** - `v` (Vector3) - the vector **Returns** - `n` (Vector3) - the normalized vector ### Normalize *Type:* FUNCTION normalize a vector to length 1 **Parameters** - `v` (Vector4) - the vector **Returns** - `n` (Vector4) - the normalized vector ### Normalize *Type:* FUNCTION normalize a quaternion to length 1 **Parameters** - `v` (Quat) - the quaternion **Returns** - `n` (Quat) - the normalized quaternion ### OrthoInverse *Type:* FUNCTION Compute the inverse of a 4x4 matrix, which is expected to be an affine matrix with an orthogonal upper-left 3x3 submatrix **Parameters** - `m` (Matrix4) - the rotation **Returns** - `r` (Matrix4) - the transposed matrix ### Point3 *Type:* TYPEDEF A 3-tuple (with 4-th element always set to 1) **Notes** - 16 byte aligned - Always size of 4 float32 - Currently scalar implementation is used on most platforms **Examples** ``` dmVMath::Point3 p = dmVMath::Point3(x, y, z); // Create new point float length_squared = p.getX() * p.getX() + p.getY() * p.getY() + p.getZ() * p.getZ(); ``` ### Quat *Type:* TYPEDEF A 4-tuple representing a rotation rotation. The xyz represents the axis, and the w represents the angle. **Notes** - 16 byte aligned - Always size of 4 float32 - Currently scalar implementation is used on most platforms **Examples** ``` dmVMath::Quat p = dmVMath::Quat(x, y, z, w); // Create new rotation. W is the angle ``` ### QuatFromAngle *Type:* FUNCTION construct a quaternion from an axis index and angle **Parameters** - `axis_index` (uint32_t) - index of the rotation axis - `radians` (float) - angle of rotation in radians **Returns** - `q` (Quat) - quaternion describing the rotation ### QuatToEuler *Type:* FUNCTION Converts a quaternion into euler angles (r0, r1, r2), based on YZX rotation order. To handle gimbal lock (singularity at r1 ~ +/- 90 degrees), the cut off is at r0 = +/- 88.85 degrees, which snaps to +/- 90. The provided quaternion is expected to be normalized. The error is guaranteed to be less than +/- 0.02 degrees **Parameters** - `q0` (float) - first imaginary axis - `q1` (float) - second imaginary axis - `q2` (float) - third imaginary axis - `q3` (float) - real part **Returns** - `euler` (Vector3) - euler angles in degrees ### Rotate *Type:* FUNCTION rotate vector using quaternion **Parameters** - `q` (Quat) - the rotation - `v` (Vector3) - the vector **Returns** - `r` (Vector3) - the rotated vector ### Slerp *Type:* FUNCTION spherical linear interpolate between two vectors **Notes** - Does not clamp t to between 0 and 1 - Unpredicatable results if a and b point in opposite direction **Parameters** - `t` (float) - the unit time - `a` (Vector3) - the start vector (t == 0) - `b` (Vector3) - the end vector (t == 1) **Returns** - `v` (Vector3) - the result vector ### Slerp *Type:* FUNCTION spherical linear interpolate between two vectors **Notes** - Does not clamp t to between 0 and 1 - Unpredicatable results if a and b point in opposite direction **Parameters** - `t` (float) - the unit time - `a` (Vector4) - the start vector (t == 0) - `b` (Vector4) - the end vector (t == 1) **Returns** - `v` (Vector4) - the result vector ### Slerp *Type:* FUNCTION Interpolates along the shortest path between two quaternions **Notes** - Does not clamp t to between 0 and 1 **Parameters** - `t` (float) - the unit time - `a` (Quat) - the start vector (t == 0) - `b` (Quat) - the end vector (t == 1) **Returns** - `v` (Quat) - the result vector ### Transpose *Type:* FUNCTION transpose matrix **Parameters** - `m` (Matrix3) - the rotation **Returns** - `r` (Matrix3) - the transposed matrix ### Transpose *Type:* FUNCTION transpose matrix **Parameters** - `m` (Matrix4) - the rotation **Returns** - `r` (Matrix4) - the transposed matrix ### Vector3 *Type:* TYPEDEF A 3-tuple (with 4-th element always set to 0) **Notes** - 16 byte aligned - Always size of 4 float32 - Currently scalar implementation is used on most platforms **Examples** ``` dmVMath::Vector3 p = dmVMath::Vector3(x, y, z); // Create new vector float length_squared = p.getX() * p.getX() + p.getY() * p.getY() + p.getZ() * p.getZ(); ``` ### Vector4 *Type:* TYPEDEF A 4-tuple **Notes** - 16 byte aligned - Always size of 4 float32 - Currently scalar implementation is used on most platforms **Examples** ``` dmVMath::Vector4 p = dmVMath::Vector4(x, y, z, w); // Create new vector float length_squared = p.getX() * p.getX() + p.getY() * p.getY() + p.getZ() * p.getZ() + p.getW() * p.getW(); ``` # WebServer {#apis:engine-dlib-src-dmsdk-dlib-webserver-h} **Namespace:** `dmWebServer` **Language:** C++ **Type:** Defold C++ **File:** `webserver.h` **Source:** `engine/dlib/src/dmsdk/dlib/webserver.h` **Include:** `dmsdk/dlib/webserver.h` Simple high-level single-threaded Web server based on dmHttpServer The web-server has a handler concept similar to servlets in Java ## API ### AddHandler *Type:* FUNCTION Add a new handler **Parameters** - `server` (HServer) - Server handle - `prefix` (const char*) - Location prefix for which locations this handler should handle - `handler_params` (HandlerParams) - Handler parameters **Returns** - `return` (Result) - RESULT_OK on success ### GetHeader *Type:* FUNCTION Get http header value for key **Parameters** - `request` (Request*) - Request - `name` (const char*) - Header key **Returns** - `return` (const char*) - Header value. NULL if the key doesn't exists ### Handler *Type:* TYPEDEF Web request handler callback **Parameters** - `user_data` (void*) - User data - `request` (Request*) - Request **Returns** - `return` (void) ### HandlerParams *Type:* STRUCT handler parameters **Members** - `m_UserData` (void*) - The user data - `m_Handler` (Handler) - The callback ### HServer *Type:* TYPEDEF web server handle ### Receive *Type:* FUNCTION Receive data **Parameters** - `request` (Request*) - Request - `buffer` (void*) - Data buffer to receive to - `buffer_size` (uint32_t) - Buffer size - `received_bytes` (uint32_t*) - Number of bytes received **Returns** - `return` (Result) - RESULT_OK on success ### RemoveHandler *Type:* FUNCTION Remove handle **Parameters** - `server` (HServer) - Server handle - `prefix` (const char*) - Prefix for handle to remove **Returns** - `return` (Result) - RESULT_OK on success ### Request *Type:* STRUCT web server request **Members** - `m_Method` (const char*) - Request method - `m_Method` (const char*) - Request resource - `m_Method` (const char*) - Content-Length header - `m_Method` (const char*) - Internal data ### Result *Type:* ENUM result codes **Members** - `RESULT_OK` - `RESULT_SOCKET_ERROR` - `RESULT_INVALID_REQUEST` - `RESULT_ERROR_INVAL` - `RESULT_HANDLER_ALREADY_REGISTRED` - `RESULT_HANDLER_NOT_REGISTRED` - `RESULT_INTERNAL_ERROR` - `RESULT_UNKNOWN` ### Send *Type:* FUNCTION Send response data **Parameters** - `request` (Request) - Request handle - `data` (void*) - Data to send - `data_length` (uint32_t) - Data-lenght to send **Returns** - `return` (Result) - RESULT_OK on success ### SendAttribute *Type:* FUNCTION Sends a header attribute **Parameters** - `request` (Request*) - Request - `key` (const char*) - the header name - `value` (const char*) - the header value **Returns** - `return` (Result) - RESULT_OK on success ### SetStatusCode *Type:* FUNCTION Set response status code. **Notes** - Only valid to invoke before #Send is invoked **Parameters** - `request` (Request*) - Request - `status_code` (int) - Status code to set **Returns** - `return` (Result) - RESULT_OK on success # Engine {#apis:engine-engine-src-dmsdk-engine-extension-hpp} **Namespace:** `dmEngine` **Language:** C++ **Type:** Defold C++ **File:** `extension.hpp` **Source:** `engine/engine/src/dmsdk/engine/extension.hpp` **Include:** `dmsdk/engine/extension.hpp` SDK Engine extension API documentation ## API ### DM_DEBUG *Type:* MACRO define for debug builds **Examples** Only enable code in debug builds ``` #if defined(DM_DEBUG) // ... #endif ``` ### DM_HEADLESS *Type:* MACRO define for headless builds **Examples** Only enable code in headless builds ``` #if defined(DM_HEADLESS) // ... #endif ``` ### DM_RELEASE *Type:* MACRO define for release builds **Examples** Only enable code in release builds ``` #if defined(DM_RELEASE) // ... #endif ``` ### GetConfigFile *Type:* FUNCTION get the config file **Parameters** - `app_params` (dmExtension::AppParams*) - The app params sent to the extension dmExtension::AppInitialize / dmExtension::AppInitialize **Returns** - `config` (dmConfigFile::HConfig) - The game project config file ### GetGameObjectRegister *Type:* FUNCTION get the game object register **Parameters** - `app_params` (dmExtension::AppParams*) - The app params sent to the extension dmExtension::AppInitialize / dmExtension::AppInitialize **Returns** - `register` (dmGameObject::HRegister) - The game object register ### GetHIDContext *Type:* FUNCTION get the hid context **Parameters** - `app_params` (dmExtension::AppParams*) - The app params sent to the extension dmExtension::AppInitialize / dmExtension::AppInitialize **Returns** - `context` (dmHID::HContext) - The hid context ### GetWebServer *Type:* FUNCTION get the web server handle **Notes** - Only valid in debug builds **Parameters** - `app_params` (dmExtension::AppParams*) - The app params sent to the extension dmExtension::AppInitialize / dmExtension::AppInitialize **Returns** - `server` (dmWebServer::HServer) - The web server handle # Engine runtime {#apis:engine-engine-src-engine_doc-h} **Namespace:** `engine` **Language:** C++ **Type:** Defold C++ **File:** `engine_doc.h` **Source:** `engine/engine/src/engine_doc.h` **Include:** `engine/engine/src/engine_doc.h` Engine runtime documentation ## API ### --config= *Type:* MACRO Override game properties with the format --config=section.key=value **Examples** ``` $ ./dmengine --config=project.mode=TEST --config=project.server=http://testserver.com ``` ### --verify-graphics-calls= *Type:* MACRO Disables OpenGL error checking. This is especially beneficial for running debug builds in the Chrome browser, in which the calls to glGetError() is notoriously slow. Default value is "true" for debug builds, and "false" for release builds. **Examples** ``` $ ./dmengine --verify-graphics-calls=false ``` ### DM_LOG_PORT *Type:* MACRO Enables receiving the log on a designated port (e.g. using telnet) Valid values are integers between [0, 65535] ### DM_QUIT_ON_ESC *Type:* MACRO Enables quitting the app directly by pressing the ESCAPE key. Set to "1" to enable this feature. ### DM_SAVE_HOME *Type:* MACRO Overrides the save directory when using sys.get_save_file() ### DM_SERVICE_PORT *Type:* MACRO Overrides the engine service port, when creating the internal http server (e.g web profiler) Valid values are integers between [0, 65535] and the string "dynamic" (which translates to 0). Default value is 8001. ### launch_project *Type:* MACRO Launch the engine with a specific project file If no project is specified, it will default to "./game.projectc", "build/default/game.projectc" **Notes** - It has to be the first argument **Examples** ``` $ ./dmengine some/folder/game.projectc ``` # Extension {#apis:engine-extension-src-dmsdk-extension-extension_gen-hpp} **Namespace:** `dmExtension` **Language:** C++ **Type:** Defold C++ **File:** `extension_gen.hpp` **Source:** `engine/extension/src/dmsdk/extension/extension_gen.hpp` **Include:** `dmsdk/extension/extension_gen.hpp` Functions for creating and controlling engine native extension libraries. ## API ### AppExitCode *Type:* ENUM Engine exit code. **Members** - `EXTENSION_APP_EXIT_CODE_NONE` - `EXTENSION_APP_EXIT_CODE_REBOOT` - `EXTENSION_APP_EXIT_CODE_EXIT` ### AppParams *Type:* STRUCT The extension app parameters **Members** - `m_ConfigFile` (HConfigFile) - Deprecated - `m_ExitStatus` (ExtensionAppExitCode) - App exit code ### AppParamsFinalize *Type:* FUNCTION Finalizes an extension app params struct (deallocates internal memory) **Parameters** - `app_params` (ExtensionAppParams*) - the params ### AppParamsGetAppExitCode *Type:* FUNCTION get the app exit code **Parameters** - `app_params` (dmExtension::AppParams*) - The app params sent to the extension dmExtension::AppInitialize / dmExtension::AppInitialize **Returns** - `code` (ExtensionAppExitCode) - engine exit code ### AppParamsGetContext *Type:* FUNCTION Gets a context using a specified name hash **Parameters** - `params` (ExtensionAppParams) - the params - `name_hash` (dmhash_t) - the context name hash **Returns** - `context` (void*) - The context, if it exists ### AppParamsGetContextByName *Type:* FUNCTION Gets a context using a specified name **Parameters** - `params` (ExtensionAppParams) - the params - `name` (const char*) - the context name **Returns** - `context` (void*) - The context, if it exists ### AppParamsInitialize *Type:* FUNCTION Initializes an extension app params struct NOTE: this is an opaque struct, do not use it's members directly! **Parameters** - `app_params` (ExtensionAppParams*) - the params ### AppParamsSetContext *Type:* FUNCTION Sets a context using a specified name **Parameters** - `params` (ExtensionAppParams) - the params - `name` (const char*) - the context name - `context` (void*) - the context **Returns** - `result` (int) - 0 if successful ### CallbackType *Type:* ENUM Extra callback type for RegisterCallback function. **Members** - `EXTENSION_CALLBACK_PRE_RENDER` - `EXTENSION_CALLBACK_POST_RENDER` ### DM_DECLARE_EXTENSION *Type:* MACRO Declare and register new extension to the engine. This macro is used to declare the extension callback functions used by the engine to communicate with the extension. **Examples** Register a new extension: ``` DM_DECLARE_EXTENSION(MyExt, "MyExt", AppInitializeMyExt, AppFinalizeMyExt, InitializeMyExt, UpdateMyExt, OnEventMyExt, FinalizeMyExt); ``` ### DM_PLATFORM_ANDROID *Type:* MACRO Set if the platform is Android ### DM_PLATFORM_HTML5 *Type:* MACRO Set if the platform is Html5 ### DM_PLATFORM_IOS *Type:* MACRO Set if the platform is iPhoneOS ### DM_PLATFORM_LINUX *Type:* MACRO Set if the platform is Linux ### DM_PLATFORM_OSX *Type:* MACRO Set if the platform is OSX ### DM_PLATFORM_WINDOWS *Type:* MACRO Set if the platform is Windows (on both x86 and x86_64) ### Event *Type:* STRUCT Extension event ### EventID *Type:* ENUM Event id enumeration. EVENT_ID_ICONIFYAPP and EVENT_ID_DEICONIFYAPP only available on **Members** - `EXTENSION_EVENT_ID_ACTIVATEAPP` - `EXTENSION_EVENT_ID_DEACTIVATEAPP` - `EXTENSION_EVENT_ID_ICONIFYAPP` - `EXTENSION_EVENT_ID_DEICONIFYAPP` - `EXTENSION_EVENT_ID_ENGINE_INITIALIZED` - `EXTENSION_EVENT_ID_ENGINE_DELETE` ### ExtensionAppExitCode *Type:* ENUM Engine exit code. **Members** - `EXTENSION_APP_EXIT_CODE_NONE` - `EXTENSION_APP_EXIT_CODE_REBOOT` - `EXTENSION_APP_EXIT_CODE_EXIT` ### ExtensionAppParams *Type:* STRUCT The extension app parameters **Members** - `m_ConfigFile` (HConfigFile) - Deprecated - `m_ExitStatus` (ExtensionAppExitCode) - App exit code ### ExtensionAppParamsFinalize *Type:* FUNCTION Finalizes an extension app params struct (deallocates internal memory) **Parameters** - `app_params` (ExtensionAppParams*) - the params ### ExtensionAppParamsGetAppExitCode *Type:* FUNCTION get the app exit code **Parameters** - `app_params` (dmExtension::AppParams*) - The app params sent to the extension dmExtension::AppInitialize / dmExtension::AppInitialize **Returns** - `code` (ExtensionAppExitCode) - engine exit code ### ExtensionAppParamsGetContext *Type:* FUNCTION Gets a context using a specified name hash **Parameters** - `params` (ExtensionAppParams) - the params - `name_hash` (dmhash_t) - the context name hash **Returns** - `context` (void*) - The context, if it exists ### ExtensionAppParamsGetContextByName *Type:* FUNCTION Gets a context using a specified name **Parameters** - `params` (ExtensionAppParams) - the params - `name` (const char*) - the context name **Returns** - `context` (void*) - The context, if it exists ### ExtensionAppParamsInitialize *Type:* FUNCTION Initializes an extension app params struct NOTE: this is an opaque struct, do not use it's members directly! **Parameters** - `app_params` (ExtensionAppParams*) - the params ### ExtensionAppParamsSetContext *Type:* FUNCTION Sets a context using a specified name **Parameters** - `params` (ExtensionAppParams) - the params - `name` (const char*) - the context name - `context` (void*) - the context **Returns** - `result` (int) - 0 if successful ### ExtensionCallbackType *Type:* ENUM Extra callback type for RegisterCallback function. **Members** - `EXTENSION_CALLBACK_PRE_RENDER` - `EXTENSION_CALLBACK_POST_RENDER` ### ExtensionDescBufferSize *Type:* FUNCTION Used when registering new extensions ### ExtensionEvent *Type:* STRUCT Extension event ### ExtensionEventID *Type:* ENUM Event id enumeration. EVENT_ID_ICONIFYAPP and EVENT_ID_DEICONIFYAPP only available on **Members** - `EXTENSION_EVENT_ID_ACTIVATEAPP` - `EXTENSION_EVENT_ID_DEACTIVATEAPP` - `EXTENSION_EVENT_ID_ICONIFYAPP` - `EXTENSION_EVENT_ID_DEICONIFYAPP` - `EXTENSION_EVENT_ID_ENGINE_INITIALIZED` - `EXTENSION_EVENT_ID_ENGINE_DELETE` ### ExtensionParams *Type:* STRUCT The global parameters avalable when registering and unregistering an extension **Members** - `m_ConfigFile` (HConfigFile) - The game project settings (including overrides and plugins) - `m_ResourceFactory` (HResourceFactory) - The game resource factory / repository - `m_L` (lua_State*) - The Lua state. ### ExtensionParamsFinalize *Type:* FUNCTION Finalizes an extension params struct (deallocates internal memory) **Parameters** - `app_params` (ExtensionParams*) - the params ### ExtensionParamsGetContext *Type:* FUNCTION Gets a context using a specified name hash **Parameters** - `params` (ExtensionParams) - the params - `name_hash` (dmhash_t) - the context name hash **Returns** - `context` (void*) - The context, if it exists ### ExtensionParamsGetContextByName *Type:* FUNCTION Gets a context using a specified name **Parameters** - `params` (ExtensionParams) - the params - `name` (const char*) - the context name **Returns** - `context` (void*) - The context, if it exists ### ExtensionParamsInitialize *Type:* FUNCTION Initializes an extension params struct NOTE: this is an opaque struct, do not use it's members directly! **Parameters** - `app_params` (ExtensionParams*) - the params ### ExtensionParamsSetContext *Type:* FUNCTION Sets a context using a specified name **Parameters** - `params` (ExtensionAppParams) - the params - `name` (const char*) - the context name - `context` (void*) - the context **Returns** - `result` (int) - 0 if successful ### ExtensionRegister *Type:* FUNCTION Extension declaration helper. Internal function. Use DM_DECLARE_EXTENSION **Parameters** - `desc` (void*) - A persistent buffer of at least 128 bytes. - `desc_size` (const char*) - size of buffer holding desc. in bytes - `name` (const char*) - extension name. human readble. max 16 characters long. - `app_initialize` (FExtensionAppInitialize) - app-init function. May be null - `app_finalize` (FExtensionAppFinalize) - app-final function. May be null - `initialize` (FExtensionInitialize) - init function. May not be 0 - `finalize` (FExtensionFinalize) - finalize function. May not be 0 - `update` (FExtensionUpdate) - update function. May be null - `on_event` (FExtensionOnEvent) - event callback function. May be null ### ExtensionRegisteriOSUIApplicationDelegate *Type:* FUNCTION Register an iOS application delegate to the engine. Multiple delegates are supported (Max 32) **Notes** - Note that the delegate needs to be registered before the UIApplicationMain in order to handle any earlier callbacks. This function is only available on iOS. [icon:ios] **Parameters** - `delegate` (void*) - An id, see: https://developer.apple.com/documentation/uikit/uiapplicationdelegate?language=objc **Examples** ```objective-c // myextension_ios.mm id g_MyApplicationDelegate; ### ExtensionResult *Type:* ENUM Result enumeration. **Members** - `EXTENSION_RESULT_OK` - `EXTENSION_RESULT_INIT_ERROR` ### ExtensionUnregisteriOSUIApplicationDelegate *Type:* FUNCTION Deregister a previously registered iOS application delegate This function is only available on iOS. **Parameters** - `delegate` (void*) - an id ### FCallback *Type:* TYPEDEF Callback typedef for functions passed to RegisterCallback(). **Parameters** - `params` (ExtensionParams) **Returns** - `return` (ExtensionResult) ### FExtensionAppFinalize *Type:* TYPEDEF Callback when the app is being finalized **Parameters** - `params` (ExtensionAppParams) **Returns** - `result` (ExtensionResult) - EXTENSION_RESULT_OK if all went ok ### FExtensionAppInitialize *Type:* TYPEDEF Callback when the app is being initialized. Called before FExtensionInitialize **Notes** - There is no guarantuee of initialization order. If an extension requires another extension to be initialized, that should be handled in [ref:FExtensionInitialize]. **Parameters** - `params` (ExtensionAppParams) **Returns** - `result` (ExtensionResult) - EXTENSION_RESULT_OK if all went ok ### FExtensionCallback *Type:* TYPEDEF Callback typedef for functions passed to RegisterCallback(). **Parameters** - `params` (ExtensionParams) **Returns** - `return` (ExtensionResult) ### FExtensionFinalize *Type:* TYPEDEF Calls for the finalization of an extension **Notes** - All extensions will be called with `FExtensionFinalize` before moving on to the next step, the [ref:FExtensionAppFinalize] **Parameters** - `params` (ExtensionParams) **Returns** - `result` (ExtensionResult) - EXTENSION_RESULT_OK if all went ok ### FExtensionInitialize *Type:* TYPEDEF Callback when the app is being finalized **Parameters** - `params` (ExtensionAppParams) **Returns** - `result` (ExtensionResult) - EXTENSION_RESULT_OK if all went ok ### FExtensionOnEvent *Type:* TYPEDEF Receives an event from the engine **Parameters** - `params` (ExtensionParams) - `event` (ExtensionEvent) - The current event ### FExtensionUpdate *Type:* TYPEDEF Updates an extension. Called for each game frame. **Parameters** - `params` (ExtensionParams) **Returns** - `result` (ExtensionResult) - EXTENSION_RESULT_OK if all went ok ### Params *Type:* STRUCT The global parameters avalable when registering and unregistering an extension **Members** - `m_ConfigFile` (HConfigFile) - The game project settings (including overrides and plugins) - `m_ResourceFactory` (HResourceFactory) - The game resource factory / repository - `m_L` (lua_State*) - The Lua state. ### ParamsFinalize *Type:* FUNCTION Finalizes an extension params struct (deallocates internal memory) **Parameters** - `app_params` (ExtensionParams*) - the params ### ParamsGetContext *Type:* FUNCTION Gets a context using a specified name hash **Parameters** - `params` (ExtensionParams) - the params - `name_hash` (dmhash_t) - the context name hash **Returns** - `context` (void*) - The context, if it exists ### ParamsGetContextByName *Type:* FUNCTION Gets a context using a specified name **Parameters** - `params` (ExtensionParams) - the params - `name` (const char*) - the context name **Returns** - `context` (void*) - The context, if it exists ### ParamsInitialize *Type:* FUNCTION Initializes an extension params struct NOTE: this is an opaque struct, do not use it's members directly! **Parameters** - `app_params` (ExtensionParams*) - the params ### ParamsSetContext *Type:* FUNCTION Sets a context using a specified name **Parameters** - `params` (ExtensionAppParams) - the params - `name` (const char*) - the context name - `context` (void*) - the context **Returns** - `result` (int) - 0 if successful ### RegisteriOSUIApplicationDelegate *Type:* FUNCTION Register an iOS application delegate to the engine. Multiple delegates are supported (Max 32) **Notes** - Note that the delegate needs to be registered before the UIApplicationMain in order to handle any earlier callbacks. This function is only available on iOS. [icon:ios] **Parameters** - `delegate` (void*) - An id, see: https://developer.apple.com/documentation/uikit/uiapplicationdelegate?language=objc **Examples** ```objective-c // myextension_ios.mm id g_MyApplicationDelegate; ### Result *Type:* ENUM Result enumeration. **Members** - `EXTENSION_RESULT_OK` - `EXTENSION_RESULT_INIT_ERROR` ### UnregisteriOSUIApplicationDelegate *Type:* FUNCTION Deregister a previously registered iOS application delegate This function is only available on iOS. **Parameters** - `delegate` (void*) - an id # Component {#apis:engine-gameobject-src-dmsdk-gameobject-component-h} **Namespace:** `dmGameObject` **Language:** C++ **Type:** Defold C++ **File:** `component.h` **Source:** `engine/gameobject/src/dmsdk/gameobject/component.h` **Include:** `dmsdk/gameobject/component.h` Api for manipulating game object components (WIP) ## API ### ComponentAddToUpdate *Type:* TYPEDEF Component add to update function. Only components called with this function should be included in the update passes. **Parameters** - `params` (const dmGameObject::ComponentAddToUpdateParams&) **Returns** - `result` (CreateResult) - CREATE_RESULT_OK on success ### ComponentAddToUpdateParams *Type:* STRUCT Parameters to ComponentAddToUpdate callback. **Members** - `m_Collection` (HCollection) - Collection handle - `m_Instance` (HInstance) - Game object instance - `m_World` (void*) - Component world - `m_Context` (void*) - User context - `m_UserData` (uintptr_t*) - User data storage pointer ### ComponentCreate *Type:* TYPEDEF Component create function. Should allocate all necessary resources for the component. The game object instance is guaranteed to have its id, scene hierarchy and transform data updated when this is called. **Parameters** - `params` (const dmGameObject::ComponentCreateParams&) **Returns** - `result` (CreateResult) - CREATE_RESULT_OK on success ### ComponentCreateParams *Type:* STRUCT Parameters to ComponentCreate callback. **Members** - `m_Instance` (HInstance) - Game object instance - `m_Position` (dmVMath::Point3) - Local component position - `m_Rotation` (dmVMath::Quat) - Local component rotation - `m_Scale` (dmVMath::Vector3) - Local component scale - `m_PropertySet` (PropertySet) - Set of properties - `m_Resource` (void*) - Component resource - `m_World` (void*) - Component world, as created in the ComponentNewWorld callback - `m_Context` (void*) - User context - `m_UserData` (uintptr_t*) - User data storage pointer - `m_ComponentIndex` (uint16_t) - Index of the component type being created (among all component types) ### ComponentDeleteWorld *Type:* TYPEDEF Component world destroy function **Parameters** - `params` (const dmGameObject::ComponentDeleteWorldParams&) **Returns** - `result` (CreateResult) - CREATE_RESULT_OK on success ### ComponentDeleteWorldParams *Type:* STRUCT Parameters to ComponentDeleteWorld callback. **Members** - `m_Context` - [type void*] Context for the component type - `m_World` - [type void*] The pointer to the world to destroy ### ComponentDestroy *Type:* TYPEDEF Component destroy function. Should deallocate all necessary resources. **Parameters** - `params` (const dmGameObject::ComponentDestroyParams&) **Returns** - `result` (CreateResult) - CREATE_RESULT_OK on success ### ComponentDestroyParams *Type:* STRUCT Parameters to ComponentDestroy callback. **Members** - `m_Collection` (HCollection) - Collection handle - `m_Instance` (HInstance) - Game object instance - `m_World` (void*) - Component world - `m_Context` (void*) - User context - `m_UserData` (uintptr_t*) - User data storage pointer ### ComponentFinal *Type:* TYPEDEF Component finalize function. Should clean up as it is called when the component is disabled. **Parameters** - `params` (const dmGameObject::ComponentFinalParams&) **Returns** - `result` (CreateResult) - CREATE_RESULT_OK on success ### ComponentFinalParams *Type:* STRUCT Parameters to ComponentFinal callback. **Members** - `m_Collection` (HCollection) - Collection handle - `m_Instance` (HInstance) - Game object instance - `m_World` (void*) - Component world - `m_Context` (void*) - User context - `m_UserData` (uintptr_t*) - User data storage pointer ### ComponentGet *Type:* TYPEDEF A simple way to get the component instance from the user_data (which was set during creation) **Parameters** - `params` (const dmGameObject::ComponentGetParams&) - Update parameters **Returns** - `component` (void*) - The internal component pointer ### ComponentGetParams *Type:* STRUCT Parameters to ComponentGet callback. **Members** - `m_World` (HComponentWorld) - Component world - `m_UserData` (HComponentInternal) - Component internal representation ### ComponentGetProperty *Type:* TYPEDEF Callback for retrieving a property value of the component. **Parameters** - `params` (const dmGameObject::ComponentGetPropertyParams&) - the parameters - `out_value` (dmGameObject::PropertyDesc&) - (out) the property **Returns** - `result` (dmGameObject::PropertyResult) - PROPERTY_RESULT_OK if retrieving the property was ok ### ComponentGetPropertyParams *Type:* STRUCT Parameters to ComponentGetProperty callback. **Members** - `m_Context` (void*) - Context for the component type - `m_World` (void*) - Component world - `m_Instance` (HInstance) - Game object instance - `m_PropertyId` (dmhash_t) - Id of the property - `m_UserData` (uintptr_t*) - User data storage pointer - `m_Options` (HPropertyOptions) - Options for getting the property ### ComponentInit *Type:* TYPEDEF Component init function. Should set the components initial state as it is called when the component is enabled. **Parameters** - `params` (const dmGameObject::ComponentInitParams&) **Returns** - `result` (CreateResult) - CREATE_RESULT_OK on success ### ComponentInitParams *Type:* STRUCT Parameters to ComponentInit callback. **Members** - `m_Collection` (HCollection) - Collection handle - `m_Instance` (HInstance) - Game object instance - `m_World` (void*) - Component world - `m_Context` (void*) - User context - `m_UserData` (uintptr_t*) - User data storage pointer ### ComponentIterProperties *Type:* TYPEDEF Callback when iterating over the properties for a component. **Notes** - This function is only available/used in debug builds, when traversing the scene graph in order to export this data for external tools (e.g. external testing libraries like Poco) **Parameters** - `pit` (dmGameObject::SceneNodePropertyIterator) - the property iterator - `node` (dmGameObject::SceneNode*) - the scene node ### ComponentNewWorld *Type:* TYPEDEF Component world create function **Parameters** - `params` (const dmGameObject::ComponentNewWorldParams&) **Returns** - `result` (CreateResult) - CREATE_RESULT_OK on success ### ComponentNewWorldParams *Type:* STRUCT Parameters to ComponentNewWorld callback. **Members** - `m_Context` (void*) - Context for the component type - `m_ComponentIndex` (uint8_t) - Component type index that can be used later with GetWorld() - `m_MaxInstances` (uint32_t) - Max component game object instance count (if applicable) - `m_World` (void**) - Out-parameter of the pointer in which to store the created world - `m_MaxComponentInstances` (uint32_t) - Max components count of this type in current collection counted at the build stage. If component in factory then value is 0xFFFFFFFF ### ComponentOnInput *Type:* TYPEDEF Component on-input function. Called when input is sent to this component **Parameters** - `params` (const dmGameObject::ComponentOnInputParams&) - Input parameters **Returns** - `result` (InputResult) - How the component handled the input ### ComponentOnInputParams *Type:* STRUCT Parameters to ComponentOnInput callback. **Members** - `m_Instance` (HInstance) - Instance handle - `m_InputAction` (const InputAction*) - Information about the input that occurred (note that input being released is also treated as input) - `m_Context` (void*) - User context - `m_UserData` (uintptr_t*) - User data storage pointer ### ComponentOnMessage *Type:* TYPEDEF Component on-message function. Called when message is sent to this component **Parameters** - `params` (const dmGameObject::ComponentOnMessageParams&) - Update parameters **Returns** - `result` (UpdateResult) - UPDATE_RESULT_OK on success ### ComponentOnMessageParams *Type:* STRUCT Parameters to ComponentOnMessage callback. **Members** - `m_Instance` (HInstance) - Instance handle - `m_World` (void*) - World - `m_Context` (void*) - User context - `m_UserData` (uintptr_t*) - User data storage pointer - `m_Message` (dmMessage::Message*) - Message ### ComponentOnReload *Type:* FUNCTION Called when the resource the component is based on has been reloaded. **Parameters** - `params` (const dmGameObject::ComponentOnReloadParams&) - the parameters ### ComponentOnReloadParams *Type:* STRUCT Parameters to ComponentOnReload callback. **Members** - `m_Instance` (HInstance) - Instance handle - `m_Resource` (void*) - Resource that was reloaded - `m_World` (void*) - Component world - `m_Context` (void*) - User context - `m_UserData` (uintptr_t*) - User data storage pointer ### ComponentSetProperties *Type:* TYPEDEF Set a property set for the component. **Parameters** - `params` (const dmGameObject::ComponentSetPropertiesParams&) - the parameters **Returns** - `result` (dmGameObject::PropertyResult) - PROPERTY_RESULT_OK if property was set ### ComponentSetPropertiesParams *Type:* STRUCT Parameters to ComponentSetProperties callback. **Members** - `m_Instance` (HInstance) - Instance handle - `m_PropertySet` (PropertySet) - Property set to use - `m_UserData` (uintptr_t*) - User data storage pointer ### ComponentSetProperty *Type:* TYPEDEF Callback for setting a property value of the component. **Parameters** - `params` (const dmGameObject::ComponentSetPropertyParams&) - the parameters **Returns** - `result` (dmGameObject::PropertyResult) - PROPERTY_RESULT_OK if property was set ### ComponentSetPropertyParams *Type:* STRUCT Parameters to ComponentSetProperty callback. **Members** - `m_Context` (void*) - Context for the component type - `m_World` (void*) - Component world - `m_Instance` (HInstance) - Game object instance - `m_PropertyId` (dmhash_t) - Id of the property - `m_UserData` (uintptr_t*) - User data storage pointer - `m_Value` (PropertyVar) - New value of the property - `m_Options` (HPropertyOptions) - Options for setting the property ### ComponentsPostUpdate *Type:* TYPEDEF Component post update function. The component state should never be modified in this function. **Parameters** - `params` (const dmGameObject::ComponentsPostUpdateParams&) - Update parameters **Returns** - `result` (UpdateResult) - UPDATE_RESULT_OK on success ### ComponentsPostUpdateParams *Type:* STRUCT Parameters for ComponentsPostUpdate callback. **Members** - `m_Collection` (HCollection) - Collection handle - `m_World` (void*) - Component world - `m_Context` (void*) - User context ### ComponentsRender *Type:* TYPEDEF Component render function. **Parameters** - `params` (const dmGameObject::ComponentsRenderParams&) - Update parameters **Returns** - `result` (UpdateResult) - UPDATE_RESULT_OK on success ### ComponentsRenderParams *Type:* STRUCT Parameters to ComponentsRender callback. **Members** - `m_Collection` (HCollection) - Collection handle - `m_World` (void*) - Component world - `m_Context` (void*) - User context ### ComponentsUpdate *Type:* TYPEDEF Component update function. Updates all component of this type for all game objects **Parameters** - `params` (const dmGameObject::ComponentsUpdateParams&) - Update parameters - `params` (dmGameObject::ComponentsUpdateResult&) - (out) Update result **Returns** - `result` (UpdateResult) - UPDATE_RESULT_OK on success ### ComponentsUpdateParams *Type:* STRUCT Parameters to ComponentsUpdate callback. **Members** - `m_Collection` (HCollection) - Collection handle - `m_UpdateContext` (const UpdateContext*) - Update context - `m_World` (void*) - Component world - `m_Context` (void*) - User context ### ComponentsUpdateResult *Type:* STRUCT Parameters to ComponentsUpdate callback. **Members** - `m_TransformsUpdated` (bool) - True if a component type updated any game object transforms ### ComponentTypeCreateCtx *Type:* STRUCT Context used when registering a new component type **Members** - `m_Config` (dmConfigFile::HConfig) - The config file - `m_Factory` (dmResource::HFactory) - The resource factory - `m_Register` (dmGameObject::HRegister) - The game object registry - `m_Script` (dmScript::HContext) - The shared script context - `m_Contexts` (dmHashTable64) - Mappings between names and contextx ### ComponentTypeGetContext *Type:* FUNCTION get the component type global context **Parameters** - `type` (HComponentType) - the type **Returns** - `context` (void*) - component type global context ### ComponentTypeGetTypeIndex *Type:* FUNCTION Get the component type index. Used for with e.g. dmGameObject::GetWorld()/GetContext() **Parameters** - `type` (HComponentType) - the type **Returns** - `type_index` (uint32_t) - The type index. ### ComponentTypeSetAddToUpdateFn *Type:* FUNCTION Set the component add-to-update callback. Called for each component instal, when the game object is spawned. **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentAddToUpdate) - callback ### ComponentTypeSetChildIteratorFn *Type:* FUNCTION set the component child iterator function. Called during inspection **Parameters** - `type` (HComponentType) - the type - `fn` (dmGameObject::FIteratorChildren) - child iterator function ### ComponentTypeSetContext *Type:* FUNCTION Set the component type global context. Usually set when registering the component type. **Parameters** - `type` (HComponentType) - the type - `context` (void*) - component type global context ### ComponentTypeSetCreateFn *Type:* FUNCTION Set the component create callback. Called when a component instance is created. **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentCreate) - callback ### ComponentTypeSetDeleteWorldFn *Type:* FUNCTION Set the world destroy callback. Called when a collection (i.e. a "world") is destroyed. **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentDeleteWorld) - callback ### ComponentTypeSetDestroyFn *Type:* FUNCTION Set the component destroy callback. Called when a component instance is destroyed. **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentDestroy) - callback ### ComponentTypeSetFinalFn *Type:* FUNCTION Set the component finalize callback. Called on each gameobject's components, during a gameobject's finalization. **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentFinal) - callback ### ComponentTypeSetFixedUpdateFn *Type:* FUNCTION Set the component update callback. Called when it's time to update all component instances. **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentsUpdate) - callback ### ComponentTypeSetGetFn *Type:* FUNCTION Set the component get callback. Called when the scripts want to retrieve the individual component user data given an url. **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentGet) - callback ### ComponentTypeSetGetPropertyFn *Type:* FUNCTION Set the component get property callback. Called when accessing a property via go.get() **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentGetProperty) - callback ### ComponentTypeSetHasUserData *Type:* FUNCTION Set the component type need for a per component instance user data. Defaults to true. **Parameters** - `type` (HComponentType) - the type - `has_user_data` (bool) - does each component instance need user data ### ComponentTypeSetInitFn *Type:* FUNCTION Set the component init callback. Called on each gameobject's components, during a gameobject's initialization. **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentInit) - callback ### ComponentTypeSetLateUpdateFn *Type:* FUNCTION Set the component late update callback. Called after regular update of all component instances but before render and before post update. **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentsUpdate) - callback ### ComponentTypeSetNewWorldFn *Type:* FUNCTION Set the new world callback. Called when a collection (i.e. a "world") is created. **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentNewWorld) - callback ### ComponentTypeSetOnInputFn *Type:* FUNCTION Set the component on-input callback. Called once per frame, before the Update function. **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentOnInput) - callback ### ComponentTypeSetOnMessageFn *Type:* FUNCTION Set the component on-message callback. Called multiple times per frame, to flush messages. **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentOnMessage) - callback ### ComponentTypeSetOnReloadFn *Type:* FUNCTION Set the component on-reload callback. Called when the resource of a component instance is reloaded. **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentOnReload) - callback ### ComponentTypeSetPostUpdateFn *Type:* FUNCTION Set the component post update callback. Called for each collection after the update, before the render. **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentsPostUpdate) - callback ### ComponentTypeSetPrio *Type:* FUNCTION Set the component type prio order. Defines the update order of the component types. **Parameters** - `type` (HComponentType) - the type - `prio` (uint16_t) - prio order ### ComponentTypeSetPropertyIteratorFn *Type:* FUNCTION set the component property iterator function. Called during inspection **Parameters** - `type` (HComponentType) - the type - `fn` (dmGameObject::FIteratorProperties) - property iterator function ### ComponentTypeSetReadsTransforms *Type:* FUNCTION Set the component type transform dependency flag. If this flag is set, it might trigger an dmGameObject::UpdateTransforms() (if there are dirty transforms) **Parameters** - `type` (HComponentType) - the type - `reads_transforms` (bool) - transform dependency flag ### ComponentTypeSetRenderFn *Type:* FUNCTION Set the component render callback. Called when it's time to render all component instances. **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentsRender) - callback ### ComponentTypeSetSetPropertiesFn *Type:* FUNCTION Set the component set properties callback. Called when the component instance is being spwned. **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentSetProperties) - callback ### ComponentTypeSetSetPropertyFn *Type:* FUNCTION Set the component set property callback. Called when accessing a property via go.set() **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentSetProperty) - callback ### ComponentTypeSetUpdateFn *Type:* FUNCTION Set the component update callback. Called when it's time to update all component instances. **Parameters** - `type` (HComponentType) - the type - `fn` (ComponentsUpdate) - callback ### DM_DECLARE_COMPONENT_TYPE *Type:* MACRO Register a new component type **Parameters** - `symbol` (symbol) - The unique C++ symbol name - `name` (const char*) - name of the component type (i.e. the resource suffix) - `create_fn` (dmGameObject::Result (*fn)(const ComponentTypeCreateCtx* ctx, HComponentType type)) - The type configuration function. May not be 0. - `destroy_fn` (dmGameObject::Result (*fn)(const ComponentTypeCreateCtx* ctx, HComponentType type)) - The type destruction function. May be 0. ### HComponentType *Type:* TYPEDEF Component type handle. It holds the life time functions for a type. # Gameobject {#apis:engine-gameobject-src-dmsdk-gameobject-gameobject-h} **Namespace:** `dmGameObject` **Language:** C++ **Type:** Defold C++ **File:** `gameobject.h` **Source:** `engine/gameobject/src/dmsdk/gameobject/gameobject.h` **Include:** `dmsdk/gameobject/gameobject.h` API for manipulating game objects ## API ### AcquireInstanceIndex *Type:* FUNCTION Retrieve an instance index from the index pool for the collection. **Parameters** - `collection` (dmGameObject::HColleciton) - Collection from which to retrieve the instance index. **Returns** - `instance` (uint32_t) - index from the index pool of collection. ### AddDynamicResourceHash *Type:* FUNCTION Adds a reference to a dynamically created resource into the collection. If the resource is not released before the collection is being destroyed, the collection will automatically free the resource. **Parameters** - `collection` (HCollection) - Collection handle - `path_hash` (dmhash_t) - resource path hash ### AssignInstanceIndex *Type:* FUNCTION Assign an index to the instance, only if the instance is not null. **Parameters** - `index` (uint32_t) - The index to assign. - `instance` (dmGameObject::HInstance) - The instance that should be assigned the index. ### CreateInstanceId *Type:* FUNCTION Creates a new unique instance ID and returns its hash. **Returns** - `id` (dmhash_t) - hash of the new unique instance id ### CreateResult *Type:* ENUM Create result enum. **Members** - `dmGameObject::CREATE_RESULT_OK` - `dmGameObject::CREATE_RESULT_UNKNOWN_ERROR` ### Delete *Type:* FUNCTION Delete gameobject instance **Parameters** - `collection` (dmGameObject::HCollection) - Gameobject collection - `instance` (dmGameObject::HInstance) - Gameobject instance - `recursive` (bool) - If true, delete child hierarchy recursively in child to parent order (leaf first) ### DeleteBones *Type:* FUNCTION Recursively delete all instances flagged as bones under the given parent instance. The order of deletion is depth-first, so that the children are deleted before the parents. **Parameters** - `parent` (HInstance) - Parent instance of the hierarchy ### GetAbsoluteIdentifier *Type:* FUNCTION Get absolute identifier relative to instance. The returned identifier is the representation of the qualified name, i.e. the path from root-collection to the sub-collection which the instance belongs to. Example: if the instance is part of a sub-collection in the root-collection named "sub" and id == "a" the returned identifier represents the path "sub.a" **Parameters** - `instance` (dmGameObject::HInstance) - Gameobject instance to get absolute identifier to - `identifier` (const char*) - Identifier relative to instance **Returns** - `return` (dmhash_t) - Absolute identifier. ### GetCollection *Type:* FUNCTION Retrieve a collection from the specified instance **Parameters** - `instance` (dmGameObject::HInstance) - Game object instance **Returns** - `collection` (dmGameObject::HInstance) - The collection the specified instance belongs to ### GetCollectionByHash *Type:* FUNCTION Retrieve a collection by socket name hash Note: in native extensions, the register can be retrieved during init using dmEngine::GetGameObjectRegister(dmExtension::AppParams *params) **Parameters** - `regist` (dmGameObject::HRegister) - Register - `socket_name` (dmhash_t) - The socket name **Returns** - `collection` (dmGameObject::HCollection) - The collection if successful. 0 otherwise. ### GetComponent *Type:* FUNCTION Get the component, component type and its world **Parameters** - `instance` (dmGameObject::HInstance) - Instance - `component_id` (dmhash_t) - Component id - `component_type` (uint32_t*) - (out) Component type. Used for validation. - `component` (HComponent*) - (out) The component. - `world` (HComponentWorld*) - (out) The component world. May be 0. **Returns** - `result` (dmGameObject::Result) - RESULT_OK if the component was found ### GetComponentId *Type:* FUNCTION Get component id from component index. **Parameters** - `instance` (dmGameObject::HInstance) - Instance - `component_index` (uint16_t) - Component index - `component_id` (dmhash_t*) - Component id as out-argument **Returns** - `result` (dmGameObject::Result) - RESULT_OK if the component was found ### GetComponentTypeIndex *Type:* FUNCTION Get the component type index **Parameters** - `collection` (HCollection) - Collection handle - `type_hash` (dmhash_t) - The hashed name of the registered component type (e.g. dmHashString("guic")) **Returns** - `type_index` (uint32_t) - The component type index. 0xFFFFFFFF if not found ### GetContext *Type:* FUNCTION Retrieve the context for a component type **Parameters** - `collection` (HCollection) - Collection handle - `component_type_index` (uint32_t) - index of the component type **Returns** - `context` (void*) - The pointer to the context, 0x0 if not found ### GetIdentifier *Type:* FUNCTION Get instance identifier **Parameters** - `instance` (dmGameObject::HInstance) - Gameobject instance **Returns** - `return` (dmhash_t) - Identifier. dmGameObject::UNNAMED_IDENTIFIER if not set. ### GetInstanceFromIdentifier *Type:* FUNCTION Get instance from identifier **Parameters** - `collection` (dmGameObject::HCollection) - Collection - `identifier` (dmhash_t) - Identifier **Returns** - `instance` (dmGameObject::HInstance) - Instance. NULL if instance isn't found. ### GetMessageSocket *Type:* FUNCTION Retrieve the message socket for the specified collection. **Parameters** - `collection` (dmGameObject::HCollection) - Collection handle **Returns** - `socket` (dmMessage::HSocket) - The message socket of the specified collection ### GetPosition *Type:* FUNCTION Get gameobject instance position **Parameters** - `instance` (dmGameObject::HInstance) - Gameobject instance **Returns** - `return` (dmVMath::Point3) - Position ### GetPropertyAsBool *Type:* FUNCTION Retrieve a boolean property from a component. **Parameters** - `instance` (HInstance) - Instance of the game object - `component_id` (dmhash_t) - Id of the component - `property_id` (dmhash_t) - Id of the property - `out_value` (bool*) - The retrieved property value **Returns** - `PROPERTY_RESULT_OK` - if the out-parameter was written ### GetPropertyAsFloat *Type:* FUNCTION Retrieve a float property from a component. **Parameters** - `instance` (HInstance) - Instance of the game object - `component_id` (dmhash_t) - Id of the component - `property_id` (dmhash_t) - Id of the property - `out_value` (float*) - The retrieved property value **Returns** - `PROPERTY_RESULT_OK` - if the out-parameter was written ### GetPropertyAsHash *Type:* FUNCTION Retrieve a hash property from a component. **Parameters** - `instance` (HInstance) - Instance of the game object - `component_id` (dmhash_t) - Id of the component - `property_id` (dmhash_t) - Id of the property - `out_value` (dmhash_t*) - The retrieved property value **Returns** - `PROPERTY_RESULT_OK` - if the out-parameter was written ### GetPropertyAsMatrix *Type:* FUNCTION Retrieve a matrix4 property from a component. **Parameters** - `instance` (HInstance) - Instance of the game object - `component_id` (dmhash_t) - Id of the component - `property_id` (dmhash_t) - Id of the property - `out_value` (dmGameObject::Matrix4*) - The retrieved property value **Returns** - `PROPERTY_RESULT_OK` - if the out-parameter was written ### GetPropertyAsQuat *Type:* FUNCTION Retrieve a quaternion property from a component. **Parameters** - `instance` (HInstance) - Instance of the game object - `component_id` (dmhash_t) - Id of the component - `property_id` (dmhash_t) - Id of the property - `out_value` (dmVMath::Quat*) - The retrieved property value **Returns** - `PROPERTY_RESULT_OK` - if the out-parameter was written ### GetPropertyAsURL *Type:* FUNCTION Retrieve a url property from a component. **Parameters** - `instance` (HInstance) - Instance of the game object - `component_id` (dmhash_t) - Id of the component - `property_id` (dmhash_t) - Id of the property - `out_value` (dmMessage::URL*) - The retrieved property value **Returns** - `PROPERTY_RESULT_OK` - if the out-parameter was written ### GetPropertyAsVector3 *Type:* FUNCTION Retrieve a vector3 property from a component. **Parameters** - `instance` (HInstance) - Instance of the game object - `component_id` (dmhash_t) - Id of the component - `property_id` (dmhash_t) - Id of the property - `out_value` (dmVMath::Vector3*) - The retrieved property value **Returns** - `PROPERTY_RESULT_OK` - if the out-parameter was written ### GetPropertyAsVector4 *Type:* FUNCTION Retrieve a vector4 property from a component. **Parameters** - `instance` (HInstance) - Instance of the game object - `component_id` (dmhash_t) - Id of the component - `property_id` (dmhash_t) - Id of the property - `out_value` (dmVMath::Vector4*) - The retrieved property value **Returns** - `PROPERTY_RESULT_OK` - if the out-parameter was written ### GetPropertyOptionsCount *Type:* FUNCTION Get the property count from a PropertyOptions container **Parameters** - `options` (HPropertyOptions) - Options handle **Returns** - `count` (uint32_t) - The number of property options ### GetPropertyOptionsIndex *Type:* FUNCTION Get the index value from a property option at a specific index **Parameters** - `options` (HPropertyOptions) - Options handle - `options_index` (int32_t) - The options index into the property options container - `result` (int32_t*) - If the option at the index is valid, store the result. Pointer is untouched otherwise **Returns** - `PROPERTY_RESULT_OK` - if the property option at the index is valid ### GetPropertyOptionsKey *Type:* FUNCTION Get the key value from a property option at a specific index **Parameters** - `options` (HPropertyOptions) - Options handle - `options_index` (int32_t) - The options index into the property options container - `result` (dmhash_t*) - If the option at the index is valid, store the result. Pointer is untouched otherwise **Returns** - `PROPERTY_RESULT_OK` - if the property option at the index is valid ### GetRotation *Type:* FUNCTION Get gameobject instance rotation **Parameters** - `instance` (dmGameObject::HInstance) - Gameobject instance **Returns** - `return` (dmGameObject::Quat) - rotation ### GetScale *Type:* FUNCTION Get gameobject instance scale **Parameters** - `instance` (dmGameObject::HInstance) - Gameobject instance **Returns** - `return` (dmGameObject::Vector3) - Non-uniform scale ### GetUniformScale *Type:* FUNCTION Get gameobject instance uniform scale **Parameters** - `instance` (dmGameObject::HInstance) - Gameobject instance **Returns** - `return` (float) - Uniform scale ### GetWorld *Type:* FUNCTION Retrieve the world in the collection connected to the supplied component **Parameters** - `collection` (HCollection) - Collection handle - `component_type_index` (uint32_t) - index of the component type **Returns** - `world` (void*) - The pointer to the world, 0x0 if not found ### GetWorldMatrix *Type:* FUNCTION Get game object instance world transform as Matrix4. **Parameters** - `instance` (dmGameObject::HInstance) - Gameobject instance **Returns** - `return` (dmGameObject::Matrix4) - World transform matrix. ### GetWorldPosition *Type:* FUNCTION Get gameobject instance world position **Parameters** - `instance` (dmGameObject::HInstance) - Gameobject instance **Returns** - `return` (dmGameObject::Point3) - World position ### GetWorldRotation *Type:* FUNCTION Get gameobject instance world rotation **Parameters** - `instance` (dmGameObject::HInstance) - Gameobject instance **Returns** - `return` (dmGameObject::Quat) - World rotation ### GetWorldScale *Type:* FUNCTION Get game object instance world transform **Parameters** - `instance` (dmGameObject::HInstance) - Gameobject instance **Returns** - `return` (dmGameObject::Vector3) - World scale ### GetWorldTransform *Type:* FUNCTION Get game object instance world transform **Parameters** - `instance` (dmGameObject::HInstance) - Gameobject instance **Returns** - `return` (dmTransform::Transform) - World transform ### GetWorldUniformScale *Type:* FUNCTION Get game object instance uniform scale **Parameters** - `instance` (dmGameObject::HInstance) - Gameobject instance **Returns** - `return` (float) - World uniform scale ### HCollection *Type:* TYPEDEF Gameobject collection handle ### HComponent *Type:* TYPEDEF Opaque handle to component instance ### HComponentInternal *Type:* TYPEDEF Opaque handle to internal representation of a component instance ### HComponentWorld *Type:* TYPEDEF Opaque handle to a component world ### HInstance *Type:* TYPEDEF Gameobject instance handle ### HProperties *Type:* TYPEDEF Gameobject properties handle ### HPropertyContainer *Type:* TYPEDEF Handle to a list of properties (gameobject_props.h) ### HPropertyOptions *Type:* TYPEDEF Handle to a list of property options ### HPrototype *Type:* TYPEDEF Gameobject prototype handle ### HRegister *Type:* TYPEDEF Collection register. ### HScript *Type:* TYPEDEF Script handle ### HScriptInstance *Type:* TYPEDEF Script instance handle ### InputAction *Type:* STRUCT Container of input related information. ### InputResult *Type:* ENUM Input result enum **Members** - `INPUT_RESULT_IGNORED` - = 0 - `INPUT_RESULT_CONSUMED` - = 1 - `INPUT_RESULT_UNKNOWN_ERROR` - = -1000 ### InstanceIdMap *Type:* TYPEDEF Used for mapping instance ids from a collection definition to newly spawned instances ### InstancePropertyContainers *Type:* TYPEDEF Contains property containers for game objects to be spawned ### INVALID_INSTANCE_POOL_INDEX *Type:* CONSTANT Value for an invalid instance index, this must be the same as defined in gamesys_ddf.proto for Create#index. ### IsBone *Type:* FUNCTION Check whether the instance is flagged as a bone. **Parameters** - `instance` (HInstance) - Instance **Returns** - `result` (bool) - True if flagged as a bone ### New *Type:* FUNCTION Create a new gameobject instance **Notes** - Calling this function during update is not permitted. Use #Spawn instead for deferred creation **Parameters** - `collection` (dmGameObject::HCollection) - Gameobject collection - `prototype_name` (const char*) - Prototype file name. May be 0. **Returns** - `instance` (dmGameObject::HInstance) - New gameobject instance. NULL if any error occured ### Playback *Type:* ENUM Playback type enum ### PropertyDesc *Type:* STRUCT Description of a property. If the property is externally mutable, m_ValuePtr points to the value and its length is m_ElementCount. m_Variant always reflects the value. **Members** - `m_ElementIds` (dmhash_t) - For composite properties (float arrays), these ids name each element - `m_Variant` (PropertyVar) - Variant holding the value - `m_ValuePtr` (float*) - Pointer to the value, only set for mutable values. The actual data type is described by the variant. - `m_ReadOnly` (uint16_t) - Determines whether we are permitted to write to this property. - `m_ValueType` (uint16_t) - Indicates type of the property (of type PropertyValueType). - `m_ArrayLength` (uint16_t) - Number of array entries, if the property is an array and zero otherwise. Max supported length is 2^14 (16384 elements) ### PropertyResult *Type:* ENUM Property result. **Members** - `dmGameObject::PROPERTY_RESULT_OK` - `dmGameObject::PROPERTY_RESULT_NOT_FOUND` - `dmGameObject::PROPERTY_RESULT_INVALID_FORMAT` - `dmGameObject::PROPERTY_RESULT_UNSUPPORTED_TYPE` - `dmGameObject::PROPERTY_RESULT_TYPE_MISMATCH` - `dmGameObject::PROPERTY_RESULT_COMP_NOT_FOUND` - `dmGameObject::PROPERTY_RESULT_INVALID_INSTANCE` - `dmGameObject::PROPERTY_RESULT_BUFFER_OVERFLOW` - `dmGameObject::PROPERTY_RESULT_UNSUPPORTED_VALUE` - `dmGameObject::PROPERTY_RESULT_UNSUPPORTED_OPERATION` - `dmGameObject::PROPERTY_RESULT_RESOURCE_NOT_FOUND` - `dmGameObject::PROPERTY_RESULT_INVALID_INDEX` - `dmGameObject::PROPERTY_RESULT_INVALID_KEY` - `dmGameObject::PROPERTY_RESULT_READ_ONLY` ### PropertyType *Type:* ENUM Property types. **Members** - `dmGameObject::PROPERTY_TYPE_NUMBER` - `dmGameObject::PROPERTY_TYPE_HASH` - `dmGameObject::PROPERTY_TYPE_URL` - `dmGameObject::PROPERTY_TYPE_VECTOR3` - `dmGameObject::PROPERTY_TYPE_VECTOR4` - `dmGameObject::PROPERTY_TYPE_QUAT` - `dmGameObject::PROPERTY_TYPE_BOOLEAN` - `dmGameObject::PROPERTY_TYPE_COUNT` ### PropertyValueType *Type:* ENUM Type of property value **Members** - `dmGameObject::PROP_VALUE_ARRAY` - `dmGameObject::PROP_VALUE_HASHTABLE` ### PropertyVar *Type:* STRUCT Property variant that holds the data for a variable **Members** - `m_Type` (dmGameObject::PropertyType) - property type - `m_Number` (double) - A floating point value (union) - `m_Hash` (dmhash_t) - A hash value (union) - `m_Url` (const uin8_t*) - An URL value (union) - `m_V4` (float) - A vector4 value (union) - `m_Bool` (bool) - A boolean value (union) ### Result *Type:* ENUM Result enumeration. **Members** - `dmGameObject::RESULT_OK` - `dmGameObject::RESULT_OUT_OF_RESOURCES` - `dmGameObject::RESULT_ALREADY_REGISTERED` - `dmGameObject::RESULT_IDENTIFIER_IN_USE` - `dmGameObject::RESULT_IDENTIFIER_ALREADY_SET` - `dmGameObject::RESULT_COMPONENT_NOT_FOUND` - `dmGameObject::RESULT_MAXIMUM_HIEARCHICAL_DEPTH` - `dmGameObject::RESULT_INVALID_OPERATION` - `dmGameObject::RESULT_RESOURCE_TYPE_NOT_FOUND` - `dmGameObject::RESULT_BUFFER_OVERFLOW` - `dmGameObject::RESULT_IDENTIFIER_INVALID` - `dmGameObject::RESULT_RESOURCE_ERROR` - `dmGameObject::RESULT_CHILD_NOT_FOUND` - `dmGameObject::RESULT_INVALID_PROPERTIES` - `dmGameObject::RESULT_UNABLE_TO_CREATE_COMPONENTS` - `dmGameObject::RESULT_UNABLE_TO_INIT_INSTANCE` - `dmGameObject::RESULT_UNKNOWN_ERROR` ### SceneNode *Type:* STRUCT Opaque struct that holds info about the current node **Notes** - The concept of a `scene node` only exists here, for the purposes of inspecting the scene graph for inspection and testing purposes only. ### SceneNodeIterator *Type:* STRUCT Opaque struct that holds info about the current position when traversing the scene ### SceneNodeProperty *Type:* STRUCT Struct that holds info about the current position when traversing the scene **Members** - `m_NameHash` (dmhash_t) - name - `m_Type` (dmGameObject::SceneNodePropertyType) - type - `m_Value` (union) - value `m_Number` : [type:double] floating point number `m_Hash` : [type:dmhash_t] The hashed value. `m_URL` : [type:char[1024]] The text representation of the url (if reverse hashes are enabled) `m_V4` : [type:float[4]] Used for Vector3, Vector4 and Quat `m_Bool` : [type:bool] A boolean value `m_Text` : [type:const char*] Text from a text property ### SceneNodePropertyIterator *Type:* STRUCT Holds the property **Members** - `m_Property` (dmGameObject::SceneNodeProperty) - property ### SceneNodePropertyType *Type:* ENUM scene node property types **Notes** - Since we don't support text properties, we'll keep a separate enum here for now **Members** - `dmGameObject::SCENE_NODE_PROPERTY_TYPE_NUMBER` - `dmGameObject::SCENE_NODE_PROPERTY_TYPE_HASH` - `dmGameObject::SCENE_NODE_PROPERTY_TYPE_URL` - `dmGameObject::SCENE_NODE_PROPERTY_TYPE_VECTOR3` - `dmGameObject::SCENE_NODE_PROPERTY_TYPE_VECTOR4` - `dmGameObject::SCENE_NODE_PROPERTY_TYPE_QUAT` - `dmGameObject::SCENE_NODE_PROPERTY_TYPE_BOOLEAN` - `dmGameObject::SCENE_NODE_PROPERTY_TYPE_TEXT` - `dmGameObject::SCENE_NODE_PROPERTY_TYPE_COUNT` ### SetBone *Type:* FUNCTION Set whether the instance should be flagged as a bone. Instances flagged as bones can have their transforms updated in a batch through SetBoneTransforms. Used for animated skeletons. **Parameters** - `instance` (HInstance) - Instance - `bone` (bool) - true if the instance is a bone ### SetBoneTransforms *Type:* FUNCTION Set the local transforms recursively of all instances flagged as bones, starting with component with id. The order of the transforms is depth-first. **Parameters** - `instance` (HInstance) - First Instance of the hierarchy to set - `component_transform` (dmTransform::Transform) - the transform for component root - `transforms` (dmTransform::Transform*) - Array of transforms to set depth-first for the bone instances - `transform_count` (uint32_t) - Size of the transforms array **Returns** - `Number` - of instances found ### SetIdentifier *Type:* FUNCTION Set instance identifier. Must be unique within the collection. **Parameters** - `collection` (dmGameObject::HCollection) - Collection - `instance` (dmGameObject::HInstance) - Instance - `identifier` (dmhash_t) - Identifier **Returns** - `result` (dmGameObject::Result) - RESULT_OK on success ### SetPosition *Type:* FUNCTION Set gameobject instance position **Parameters** - `instance` (dmGameObject::HInstance) - Gameobject instance - `position` (dmVMath::Point3) - New Position ### SetPropertyFromBool *Type:* FUNCTION Sets the value of a boolean property on a component. **Parameters** - `instance` (HInstance) - Instance of the game object - `component_id` (dmhash_t) - Id of the component - `property_id` (dmhash_t) - Id of the property - `value` (bool) - Value of the property **Returns** - `PROPERTY_RESULT_OK` - if the value could be set ### SetPropertyFromHash *Type:* FUNCTION Sets the value of a hash property on a component. **Parameters** - `instance` (HInstance) - Instance of the game object - `component_id` (dmhash_t) - Id of the component - `property_id` (dmhash_t) - Id of the property - `value` (dmhash_t) - Value of the property **Returns** - `PROPERTY_RESULT_OK` - if the value could be set ### SetPropertyFromHash *Type:* FUNCTION Sets the value of a float property on a component. **Parameters** - `instance` (HInstance) - Instance of the game object - `component_id` (dmhash_t) - Id of the component - `property_id` (dmhash_t) - Id of the property - `value` (float) - Value of the property **Returns** - `PROPERTY_RESULT_OK` - if the value could be set ### SetPropertyFromMatrix4 *Type:* FUNCTION Sets the value of a matrix4 property on a component. **Parameters** - `instance` (HInstance) - Instance of the game object - `component_id` (dmhash_t) - Id of the component - `property_id` (dmhash_t) - Id of the property - `value` (dmVMath::Matrix4) - Value of the property **Returns** - `PROPERTY_RESULT_OK` - if the value could be set ### SetPropertyFromQuat *Type:* FUNCTION Sets the value of a quaternion property on a component. **Parameters** - `instance` (HInstance) - Instance of the game object - `component_id` (dmhash_t) - Id of the component - `property_id` (dmhash_t) - Id of the property - `value` (dmVMath::Quat) - Value of the property **Returns** - `PROPERTY_RESULT_OK` - if the value could be set ### SetPropertyFromURL *Type:* FUNCTION Sets the value of a URL property on a component. **Parameters** - `instance` (HInstance) - Instance of the game object - `component_id` (dmhash_t) - Id of the component - `property_id` (dmhash_t) - Id of the property - `value` (dmMessage::URL) - Value of the property **Returns** - `PROPERTY_RESULT_OK` - if the value could be set ### SetPropertyFromVector3 *Type:* FUNCTION Sets the value of a vector3 property on a component. **Parameters** - `instance` (HInstance) - Instance of the game object - `component_id` (dmhash_t) - Id of the component - `property_id` (dmhash_t) - Id of the property - `value` (dmVMath::vector3) - Value of the property **Returns** - `PROPERTY_RESULT_OK` - if the value could be set ### SetPropertyFromVector4 *Type:* FUNCTION Sets the value of a vector4 property on a component. **Parameters** - `instance` (HInstance) - Instance of the game object - `component_id` (dmhash_t) - Id of the component - `property_id` (dmhash_t) - Id of the property - `value` (dmVMath::Vector4) - Value of the property **Returns** - `PROPERTY_RESULT_OK` - if the value could be set ### SetRotation *Type:* FUNCTION Set gameobject instance rotation **Parameters** - `instance` (dmGameObject::HInstance) - Gameobject instance - `rotation` (dmVmath::Quat) - New rotation ### SetScale *Type:* FUNCTION Set gameobject instance uniform scale **Parameters** - `instance` (dmGameObject::HInstance) - Gameobject instance - `scale` (float) - New uniform scale ### SetScale *Type:* FUNCTION Set gameobject instance non-uniform scale **Parameters** - `instance` (dmGameObject::HInstance) - Gameobject instance - `scale` (dmVmath::Vector3) - New non-uniform scale ### SetScaleXY *Type:* FUNCTION Set gameobject instance x and y scale **Parameters** - `instance` (dmGameObject::HInstance) - Gameobject instance - `scale_x` (float) - New x scale - `scale_y` (float) - New y scale ### Spawn *Type:* FUNCTION Spawns a new gameobject instance. The actual creation is performed after the update is completed. **Parameters** - `collection` (HCollection) - Gameobject collection - `prototype` (HPrototype) - Prototype - `prototype_name` (const char*) - Prototype file name (.goc) - `id` (dmhash_t) - Id of the spawned instance - `properties` (HPropertyContainer) - Container with override properties - `position` (dmVMath::Vector3) - Position of the spawed object - `rotation` (dmVMath::Quat) - Rotation of the spawned object - `scale` (dmVMath::Vector3) - Scale of the spawned object return instance HInstance the spawned instance, 0 at failure ### TraverseGetRoot *Type:* FUNCTION Gets the top node of the whole game (the main collection) **Notes** - The dmGameObject::HRegister is obtained from the `dmEngine::GetGameObjectRegister(dmExtension::AppParams)` - Traversing the scene like this is not efficient. These functions are here for inspection and testing purposes only. **Parameters** - `regist` (dmGameObject::HRegister) - the full gameobject register - `node` (dmGameObject::HRegister) - the node to inspect **Returns** - `result` (bool) - True if successful **Examples** The following examples show how to iterate over currently loaded scene graph ``` void OutputNode(dmGameObject::SceneNode* node) { dmGameObject::SceneNodeIterator it = dmGameObject::TraverseIterateChildren(node); while(dmGameObject::TraverseIterateNext(&it)) { OutputProperties(&it.m_Node); // see dmGameObject::TraverseIterateProperties() OutputNode(&it.m_Node); } } bool OutputScene(HRegister regist) { dmGameObject::SceneNode root; if (!dmGameObject::TraverseGetRoot(regist, &root)) return false; OutputNode(&node); } ``` ### TraverseIterateChildren *Type:* FUNCTION Get a scene node iterator for the nodes' children **Parameters** - `node` (dmGameObject::SceneNode*) - the parent node **Returns** - `iterator` (dmGameObject::SceneNodeIterator) - the iterator ### TraverseIterateNext *Type:* FUNCTION Step a scene node iterator to the next sibling **Parameters** - `it` (dmGameObject::SceneNodeIterator*) - the iterator **Returns** - `result` (bool) - true if successful. false if the iterator is finished ### TraverseIterateProperties *Type:* FUNCTION Create a scene node traversal property iterator **Notes** - Getting the properties like this is not efficient. These functions are here for inspection and testing purposes only. - Reverse hashes via `dmHashReverseSafe64()` isn't available in release builds. **Parameters** - `node` (dmGameObject::SceneNode*) - the node to inspect **Returns** - `iterator` (dmGameObject::SceneNodePropertyIterator) - the property iterator **Examples** The following examples show how to iterate over the properties of a node ``` dmGameObject::SceneNodePropertyIterator pit = TraverseIterateProperties(node); while(dmGameObject::TraverseIteratePropertiesNext(&pit)) { const char* name = dmHashReverseSafe64(pit.m_Property.m_NameHash); switch(pit.m_Property.m_Type) { case dmGameObject::SCENE_NODE_PROPERTY_TYPE_NUMBER: ... ... } } ``` ### TraverseIteratePropertiesNext *Type:* FUNCTION Steps the scene node traversal property iterator to the next property **Parameters** - `it` (dmGameObject::SceneNodePropertyIterator*) - the iterator **Returns** - `finished` (bool) - True if the iterator it valid, false if the iterator is finished. ### UpdateContext *Type:* STRUCT Update context **Members** - `m_TimeScale` (float) - the scaling factor what was applied on the dt (i.e. the collection update time scale) - `m_DT` (float) - the delta time elapsed since last frame (seconds) - `m_FixedUpdateFrequency` (uint32_t) - Number of of calls per second to the FixedUpdate of each component ### UpdateResult *Type:* ENUM Update result enum. **Members** - `dmGameObject::UPDATE_RESULT_OK` - `dmGameObject::UPDATE_RESULT_UNKNOWN_ERROR` # PropertyContainer {#apis:engine-gameobject-src-dmsdk-gameobject-gameobject_props-h} **Namespace:** `dmGameObject` **Language:** C++ **Type:** Defold C++ **File:** `gameobject_props.h` **Source:** `engine/gameobject/src/dmsdk/gameobject/gameobject_props.h` **Include:** `dmsdk/gameobject/gameobject_props.h` API for game object property container ## API ### HPropertyContainer *Type:* TYPEDEF Opaque handle to a list of properties ### HPropertyContainerBuilder *Type:* TYPEDEF Opaque handle to a property container builder ### PropertyContainerBuilderParams *Type:* STRUCT PropertyContainerBuilderParams Helper struct to create a property container builder. It is required to fill out how many items of each type that is wanted. **Parameters** - `m_NumberCount` (int32_t) - Number of items of type float - `m_HashCount` (int32_t) - Number of items of type dmhash_t - `m_URLStringCount` (int32_t) - Number of items of type const char* - `m_URLStringSize` (int32_t) - Size of all url strings combined, including null terminators - `m_URLCount` (int32_t) - Number of items of type dmMessage::URL - `m_Vector3Count` (int32_t) - Number of items of type vector3 (float[3]) - `m_Vector4Count` (int32_t) - Number of items of type vector4 (float[4]) - `m_QuatCount` (int32_t) - Number of items of type quaternion (float[4]) - `m_BoolCount` (int32_t) - Number of items of type bool ### PropertyContainerCopy *Type:* FUNCTION Allocates and copies a property container **Parameters** - `original` (HPropertyContainer) - The original property container **Returns** - `container` (HPropertyContainer) - The new property container ### PropertyContainerCreate *Type:* FUNCTION Creates the final property container **Parameters** - `builder` (HPropertyContainerBuilder) - The property container builder **Returns** - `container` (HPropertyContainer) - The property container ### PropertyContainerCreateBuilder *Type:* FUNCTION Create a property container builder with memory preallocated **Parameters** - `params` (PropertyContainerBuilderParams) - The params holding the memory requirements **Returns** - `container` (HPropertyContainerBuilder) - The builder ### PropertyContainerDestroy *Type:* FUNCTION Deallocates a property container **Parameters** - `container` (HPropertyContainer) - The property container ### PropertyContainerMerge *Type:* FUNCTION Merges two containers into a newly allocated container The properties in the overrides container will take presedence. **Parameters** - `original` (HPropertyContainer) - The original property container - `overrides` (HPropertyContainer) - The container with override properties **Returns** - `container` (HPropertyContainer) - The merged property container ### PropertyContainerPushBool *Type:* FUNCTION Add a property of type bool to the container **Parameters** - `builder` (HPropertyContainerBuilder) - The container builder - `id` (dmhash_t) - The id of the property - `value` (bool) - The value of the property ### PropertyContainerPushFloat *Type:* FUNCTION Add a property of type float to the container **Parameters** - `builder` (HPropertyContainerBuilder) - The container builder - `id` (dmhash_t) - The id of the property - `value` (float) - The value of the property ### PropertyContainerPushHash *Type:* FUNCTION Add a property of type dmhash_t to the container **Parameters** - `builder` (HPropertyContainerBuilder) - The container builder - `id` (dmhash_t) - The id of the property - `value` (dmhash_t) - The value of the property ### PropertyContainerPushQuat *Type:* FUNCTION Add a property of type float4 to the container **Parameters** - `builder` (HPropertyContainerBuilder) - The container builder - `id` (dmhash_t) - The id of the property - `values` (float*) - The value of the property (4 floats) ### PropertyContainerPushURL *Type:* FUNCTION Add a property of type dmMessage::URL to the container **Parameters** - `builder` (HPropertyContainerBuilder) - The container builder - `id` (dmhash_t) - The id of the property - `value` (dmMessage::URL) - The value of the property ### PropertyContainerPushURLString *Type:* FUNCTION Add a property of type (url) string to the container **Parameters** - `builder` (HPropertyContainerBuilder) - The container builder - `id` (dmhash_t) - The id of the property - `value` (const char*) - The value of the property ### PropertyContainerPushVector3 *Type:* FUNCTION Add a property of type float3 to the container **Parameters** - `builder` (HPropertyContainerBuilder) - The container builder - `id` (dmhash_t) - The id of the property - `values` (float*) - The value of the property (3 floats) ### PropertyContainerPushVector4 *Type:* FUNCTION Add a property of type float4 to the container **Parameters** - `builder` (HPropertyContainerBuilder) - The container builder - `id` (dmhash_t) - The id of the property - `values` (float*) - The value of the property (4 floats) # Script {#apis:engine-gameobject-src-dmsdk-gameobject-script-h} **Namespace:** `dmGameObject` **Language:** C++ **Type:** Defold C++ **File:** `script.h` **Source:** `engine/gameobject/src/dmsdk/gameobject/script.h` **Include:** `dmsdk/gameobject/script.h` GameObject script API documentation ## API ### PostDDF *Type:* FUNCTION Sends a script message. Wraps the message in a dmGameSystemDDF::ScriptMessage struct. **Template Parameters** - `T` **Parameters** - `message` (T*) - The ddf message to send - `sender` (dmMessage::Message*) - The sender - `receiver` (dmMessage::Message*) - The receiver - `function_ref` (int) - The function ref. 0 wil cause the "on_message" to be called - `unref_function_after_call` (bool) - call dmScript::UnrefInInstance on the function_ref after the dmScript::PCall is made **Returns** - `success` (bool) - true if successful ### PostScriptUnrefMessage *Type:* FUNCTION Sends a script message to unreference a script object **Parameters** - `sender` (dmMessage::Message*) - The sender - `receiver` (dmMessage::Message*) - The receiver - `reference` (int) - The reference to remove **Returns** - `success` (Result) - RESULT_OK if successful ### PropertyContainerCreateFromLua *Type:* FUNCTION Creates a property container from a lua table **Parameters** - `L` (lua_State*) - The lua state - `index` (int) - The lua stack index of the lua table **Returns** - `container` (HPropertyContainer) - The property container # Collection factory {#apis:engine-gamesys-src-dmsdk-gamesys-components-comp_collection_factory-h} **Namespace:** `dmGameSystem` **Language:** C++ **Type:** Defold C++ **File:** `comp_collection_factory.h` **Source:** `engine/gamesys/src/dmsdk/gamesys/components/comp_collection_factory.h` **Include:** `dmsdk/gamesys/components/comp_collection_factory.h` API for spawning collections from a collection factory component. ## API ### CompCollectionFactorySpawn *Type:* FUNCTION Spawns a collection of gameobjects in a collection using a collection factory component. **Parameters** - `world` (HCollectionFactoryWorld) - Collection factory world - `component` (HCollectionFactoryComponent) - Collection factory component - `collection` (HCollection) - Gameobject collection to spawn into - `id_prefix` (const char*) - Prefix for the spawned instance identifiers. Must start with a forward slash (/). Must be unique within the collection. Pass nullptr to automatically generate a unique identifier prefix (e.g. /collection1, /collection2 etc.). - `position` (dmVMath::Point3) - Position of the spawned objects - `rotation` (dmVMath::Quat) - Rotation of the spawned objects - `scale` (dmVMath::Vector3) - Scale of the spawned objects - `properties` (dmGameObject::InstancePropertyContainers) - Property containers with override properties - `out_instances` (dmGameObject::InstanceIdMap) - A map with the spawned instance id's **Returns** - `result` (dmGameObject::Result) - Result of the operation # Factory {#apis:engine-gamesys-src-dmsdk-gamesys-components-comp_factory-h} **Namespace:** `dmGameSystem` **Language:** C++ **Type:** Defold C++ **File:** `comp_factory.h` **Source:** `engine/gamesys/src/dmsdk/gamesys/components/comp_factory.h` **Include:** `dmsdk/gamesys/components/comp_factory.h` API for spawning gameobject instances from a factory component. ## API ### CompFactorySpawn *Type:* FUNCTION Spawns a new gameobject instance in a collection using a factory component. **Parameters** - `world` (HFactoryWorld) - Factory world - `component` (HFactoryComponent) - Factory component - `collection` (HCollection) - Gameobject collection to spawn into - `id` (dmhash_t) - Identifier for the new instance. Must be unique within the collection. Pass 0 to automatically generate a unique identifier (e.g. /instance1, /instance2 etc.). - `position` (dmVMath::Point3) - Position of the spawned object - `rotation` (dmVMath::Quat) - Rotation of the spawned object - `scale` (dmVMath::Vector3) - Scale of the spawned object - `properties` (dmGameObject::HPropertyContainer) - Property container with override properties - `out_instance` (dmGameObject::HInstance) - Output parameter for the new instance **Returns** - `result` (dmGameObject::Result) - Result of the operation # GameSystem GUI Component {#apis:engine-gamesys-src-dmsdk-gamesys-components-comp_gui-h} **Namespace:** `dmGameSystem` **Language:** C++ **Type:** Defold C++ **File:** `comp_gui.h` **Source:** `engine/gamesys/src/dmsdk/gamesys/components/comp_gui.h` **Include:** `dmsdk/gamesys/components/comp_gui.h` Per-property registration functions for GUI component extensions. ## API ### CompGuiPropertyGetterFn *Type:* TYPEDEF GUI component property getter function **Parameters** - `scene` (dmGui::HScene) - The GUI scene - `params` (dmGameObject::ComponentGetPropertyParams) - Property parameters - `out_value` (dmGameObject::PropertyDesc&) - Output value **Returns** - `return` (dmGameObject::PropertyResult) - PROPERTY_RESULT_OK on success ### CompGuiPropertySetterFn *Type:* TYPEDEF GUI component property setter function **Parameters** - `scene` (dmGui::HScene) - The GUI scene - `params` (dmGameObject::ComponentSetPropertyParams) - Property parameters **Returns** - `return` (dmGameObject::PropertyResult) - PROPERTY_RESULT_OK on success # Model {#apis:engine-gamesys-src-dmsdk-gamesys-components-comp_model-h} **Namespace:** `dmGameSystem` **Language:** C++ **Type:** Defold C++ **File:** `comp_model.h` **Source:** `engine/gamesys/src/dmsdk/gamesys/components/comp_model.h` **Include:** `dmsdk/gamesys/components/comp_model.h` API for interacting with model components. ## API ### CompModelPlayAnimation *Type:* FUNCTION Play a model animation. **Parameters** - `world` (HModelWorld) - Model world. - `component` (HModelComponent) - Model component. - `anim_id` (dmhash_t) - Animation to play. - `playback` (dmRig::RigPlayback) - Playback mode. - `blend_duration` (float) - Duration of a linear blend between the current and new animation. - `offset` (float) - The normalized initial value of the animation cursor when the animation starts playing. - `playback_rate` (float) - The rate with which the animation will be played. Must be positive. - `callback` (FModelAnimationCallback) - Optional function callback to send play events to. - `callback_ctx` (void*) - Optional function callback context (only when callback is set) **Returns** - `result` (dmRig::Result) - Result of the operation. ### FModelAnimationCallback *Type:* FUNCTION Model animation callback function. **Parameters** - `user_ctx` (void*) - User context - `event_type` (dmRig::RigEventType) - Animation event type - `event_data` (void*) - Animation event data # GameSystem Gui {#apis:engine-gamesys-src-dmsdk-gamesys-gui-h} **Namespace:** `dmGameSystem` **Language:** C++ **Type:** Defold C++ **File:** `gui.h` **Source:** `engine/gamesys/src/dmsdk/gamesys/gui.h` **Include:** `dmsdk/gamesys/gui.h` Built-in scripting functions. ## API ### CompGuiNodeTypeCtx *Type:* STRUCT Gui component node type create/destroy context ### DM_DECLARE_COMPGUI_TYPE *Type:* MACRO Registers a new gui node type to the Gui component **Parameters** - `symbol` (symbol) - The unique C++ symbol name - `name` (const char*) - The name of the node type - `type_create_fn` (GuiNodeTypeCreateFunction) - the create function - `type_destroy_fn` (GuiNodeTypeDestroyFunction) - the destroy function. May be 0 ### GuiNodeType *Type:* STRUCT Gui component node type ### GuiNodeTypeCreateFunction *Type:* TYPEDEF ### GuiNodeTypeDestroyFunction *Type:* TYPEDEF # Property {#apis:engine-gamesys-src-dmsdk-gamesys-property-h} **Namespace:** `dmGameSystem` **Language:** C++ **Type:** Defold C++ **File:** `property.h` **Source:** `engine/gamesys/src/dmsdk/gamesys/property.h` **Include:** `dmsdk/gamesys/property.h` Property functions. ## API ### GetResourceProperty *Type:* FUNCTION Gets the resource path hash **Parameters** - `property` (const PropVector4&) - the property - `resource` (void*) - the resource to get the - `out_value` (dmGameObject::PropertyDesc&) - the out property **Returns** - `result` (dmGameObject::PropertyResult) - RESULT_OK if successful ### IsReferencingProperty *Type:* FUNCTION Checks if the name matches any field in the property **Parameters** - `property` (const PropVector3&) - the property - `query` (dmhash_t) - the name to look for (e.g. hash("pos.x")) **Returns** - `result` (bool) - true if the property contains the name ### IsReferencingProperty *Type:* FUNCTION Checks if the name matches any field in the property **Parameters** - `property` (const PropVector4&) - the property - `query` (dmhash_t) - the name to look for (e.g. hash("pos.x")) **Returns** - `result` (bool) - true if the property contains the name ### PropVector3 *Type:* STRUCT ### PropVector4 *Type:* STRUCT ### SetResourceProperty *Type:* FUNCTION Updates the reference count of the resources, and returns the new resource. **Parameters** - `factory` (dmGameObject::HFactory) - the factory - `value` (const dmGameObject::PropertyVar&) - the property containing the hash of the resources to get - `ext` (dmhash_t) - the hash of the resource file suffix (without the "."). E.g. hash("spritec") - `out_resource` (void**) - pointer to the current resource. Will also get the pointer to the new resource. **Returns** - `result` (dmGameObject::PropertyResult) - RESULT_OK if successful # Component Render Constants {#apis:engine-gamesys-src-dmsdk-gamesys-render_constants-h} **Namespace:** `dmGameSystem` **Language:** C++ **Type:** Defold C++ **File:** `render_constants.h` **Source:** `engine/gamesys/src/dmsdk/gamesys/render_constants.h` **Include:** `dmsdk/gamesys/render_constants.h` Api for setting and updating component render constants ## API ### AreRenderConstantsUpdated *Type:* FUNCTION check if the constants have changed **Parameters** - `constants` (dmGameSystem::HComponentRenderConstants) - the constants **Returns** - `result` (int) - non zero if the constants were changed ### ClearRenderConstant *Type:* FUNCTION Removes a render constant from the container **Parameters** - `constants` (dmGameSystem::HComponentRenderConstants) - the constants - `name_hash` (dmhash_t) - the hashed name of the constant **Returns** - `result` (int) - non zero if the constant was removed ### CompGetConstantCallback *Type:* TYPEDEF Used in GetMaterialConstant to resolve a render constant's value ### CompSetConstantCallback *Type:* TYPEDEF Used in SetMaterialConstant to set a render constant's value ### CreateRenderConstants *Type:* FUNCTION Create a new HComponentRenderConstants container **Returns** - `constants` (dmGameSystem::HComponentRenderConstants) ### DestroyRenderConstants *Type:* FUNCTION Destroys a render constants container **Parameters** - `constants` (dmGameSystem::HComponentRenderConstants) - (must not be 0) ### EnableRenderObjectConstants *Type:* FUNCTION set the constants of a render object **Parameters** - `ro` (dmRender::RenderObject*) - the render object - `constants` (dmGameSystem::HComponentRenderConstants) - the constants ### GetRenderConstant *Type:* FUNCTION Destroys a render constants container **Parameters** - `constants` (dmGameSystem::HComponentRenderConstants) - the constants - `name_hash` (dmhash_t) - the hashed name of the property - `out_constant` (dmRender::Constant**) - the pointer where to store the constant **Returns** - `result` (bool) - returns true if the constant exists ### GetRenderConstant *Type:* FUNCTION Get a render constant by index **Parameters** - `constants` (dmGameSystem::HComponentRenderConstants) - the constants - `index` (uint32_t) - the index **Returns** - `constant` (dmRender::HConstant) - the pointer where to store the constant ### GetRenderConstantCount *Type:* FUNCTION Get the number of render constants **Parameters** - `constants` (dmGameSystem::HComponentRenderConstants) - the constants **Returns** - `size` (uint32_t) - returns the number of set constants ### HashRenderConstants *Type:* FUNCTION Hashes the constants **Notes** - Also updates the internal state of the constants container. After a call to this function, the `AreRenderConstantsUpdated` will always return false. **Parameters** - `constants` (dmGameSystem::HComponentRenderConstants) - the constants - `state` (HashState32*) - the hash state to update ### HashState32 *Type:* TYPEDEF Found in hash.h ### HComponentRenderConstants *Type:* TYPEDEF Render constants handle ### SetRenderConstant *Type:* FUNCTION Set a render constant by name. The constant must exist in the material **Parameters** - `constants` (dmGameSystem::HComponentRenderConstants) - the render constants buffer - `material` (dmRender::HMaterial) - the material to get default values from if constant didn't already exist in the render constants buffer - `name_hash` (dmhash_t) - the hashed name of the constant - `value_index` (uint32_t) - index of the constant value to set, if the constant is an array - `element_index` (uint32_t*) - pointer to the index of the element (in range [0,3]). May be 0 - `var` (const dmGameObject::PropertyVar&) - the constant value ### SetRenderConstant *Type:* FUNCTION Set a render constant by name. The constant must exist in the material **Parameters** - `constants` (dmGameSystem::HComponentRenderConstants) - the constants - `name_hash` (dmhash_t) - the hashed name of the constant - `values` (dmVMath::Vector4*) - the values - `num_values` (uint32_t) - number of values in the array # Data Resource {#apis:engine-gamesys-src-dmsdk-gamesys-resources-res_data-h} **Namespace:** `dmGameSystem` **Language:** C++ **Type:** Defold C++ **File:** `res_data.h` **Source:** `engine/gamesys/src/dmsdk/gamesys/resources/res_data.h` **Include:** `dmsdk/gamesys/resources/res_data.h` Helper types and accessors for the data resource type (`.datac`). ## API ### DataResource *Type:* STRUCT This struct is an opaque handle managed by the engine. Use GetDDFData() to access the underlying protobuf message for read-only inspection. ### GetDDFData *Type:* FUNCTION Returns a pointer to the decoded dmGameSystemDDF::Data protobuf message contained in the given data resource. The lifetime of the returned pointer is tied to the lifetime of the resource. It must not be freed by the caller. **Parameters** - `res` (DataResource*) - Data resource handle **Returns** - `data` (const dmGameSystemDDF::Data*) - Pointer to the DDF data message, or 0 if the resource is invalid. # Font Resource {#apis:engine-gamesys-src-dmsdk-gamesys-resources-res_font-h} **Namespace:** `dmGameSystem` **Language:** C++ **Type:** Defold C++ **File:** `res_font.h` **Source:** `engine/gamesys/src/dmsdk/gamesys/resources/res_font.h` **Include:** `dmsdk/gamesys/resources/res_font.h` Font resource functions. ## API ### FontInfo *Type:* STRUCT Used to retrieve the information of a font. **Members** - `m_Size` (uint32_t) - The size of the font (in points) - `m_ShadowX` (float) - The shadow distance in X-axis (in pixels) - `m_ShadowY` (float) - The shadow distance in Y-axis (in pixels) - `m_ShadowBlur` (uint32_t) - The shadow blur spread [0.255] (in pixels) - `m_ShadowAlpha` (float) - The shadow alpha value [0..255] - `m_Alpha` (float) - The alpha value [0..255] - `m_OutlineAlpha` (float) - The outline alpha value [0..255] - `m_OutlineWidth` (float) - The outline size (in pixels) - `m_OutputFormat` (dmRenderDDF::FontTextureFormat) - The type of font (bitmap or distance field) - `m_RenderMode` (dmRenderDDF::FontRenderMode) - Single or multi channel ### FontResource *Type:* STRUCT Handle to font resource ### FPrewarmTextCallback *Type:* TYPEDEF **Parameters** - `ctx` (void*) - The callback context - `result` (int) - The result of the prewarming. Non zero if successful - `errmsg` (const char*) - An error message if not successful. ### PrewarmText *Type:* FUNCTION Make sure each glyph in the text gets rasterized and put into the glyph cache **Parameters** - `font` (FontResource*) - The font resource - `text` (const char*) - The text (utf8) - `cbk` (FPrewarmTextCallback) - The callback is called when the last item is done - `cbk_ctx` (void*) - The callback context **Returns** - `result` (dmResource::Result) - RESULT_OK if successful ### ResFontAddFontByPath *Type:* FUNCTION add a ttf font to a font collection **Notes** - Loads the resource if not already loaded **Parameters** - `factory` (dmResource::HFactory) - The factory - `font` (FontResource*) - The font collection (.fontc) - `ttf_path` (const char*) - The .ttf path **Returns** - `result` (dmResource::Result) - RESULT_OK if successful ### ResFontAddFontByPathHash *Type:* FUNCTION add a ttf font to a font collection **Notes** - the ttf resource must already be loaded **Parameters** - `factory` (dmResource::HFactory) - The factory - `font` (FontResource*) - The font collection (.fontc) - `ttf_hash` (dmhash_t) - The ttf path hash (.ttf) **Returns** - `result` (dmResource::Result) - RESULT_OK if successful ### ResFontAddGlyph *Type:* FUNCTION **Parameters** - `font` (FontResource*) - The font resource - `hfont` (HFont) - The font the glyph was created from - `glyph_index` (uint32_t) - The glyph index **Returns** - `result` (bool) - true if the glyph already has rasterized bitmap data ### ResFontAddGlyph *Type:* FUNCTION **Parameters** - `font` (FontResource*) - The font resource - `hfont` (HFont) - The font the glyph was created from - `glyph` (FontGlyph*) - The glyph **Returns** - `result` (dmResource::Result) - RESULT_OK if successful ### ResFontGetFontCollection *Type:* FUNCTION **Parameters** - `resource` (FontResource*) - The font resource **Returns** - `font_collection` (HFontCollection*) - The font collection if successful. 0 otherwise. ### ResFontGetHandle *Type:* FUNCTION **Parameters** - `font` (FontResource*) - The font resource **Returns** - `result` (dmRender::HFontMap) - Handle to a font if successful. 0 otherwise. ### ResFontGetInfo *Type:* FUNCTION **Parameters** - `font` (FontResource*) - The font resource to query - `info` (FontInfo*) - The output info (out) **Returns** - `result` (dmResource::Result) - RESULT_OK if successful ### ResFontGetPathHashFromFont *Type:* FUNCTION **Parameters** - `resource` (FontResource*) - The font resource - `font` (HFont) - The font **Returns** - `path_hash` (dmhash_t) - The path hash to the associated TTFresource* ### ResFontGetTTFResourceFromFont *Type:* FUNCTION **Parameters** - `resource` (FontResource*) - The font resource - `font` (HFont) - The font **Returns** - `ttfresource` (TTFResource*) - The ttfresource if successful. 0 otherwise. ### ResFontGetVersion *Type:* FUNCTION **Parameters** - `font` (FontResource*) - The font resource **Returns** - `version` (uint32_t) - Monotonic layout version for the font resource. ### ResFontRemoveFont *Type:* FUNCTION remove a ttf font from a font collection **Parameters** - `factory` (dmResource::HFactory) - The factory - `font` (FontResource*) - The font collection (.fontc) - `ttf_hash` (dmhash_t) - The ttf path hash (.ttf) **Returns** - `result` (dmResource::Result) - RESULT_OK if successful ### SDF_EDGE_VALUE *Type:* CONSTANT The edge value of an sdf glyph bitmap # Light Resource {#apis:engine-gamesys-src-dmsdk-gamesys-resources-res_light-h} **Namespace:** `dmGameSystem` **Language:** C++ **Type:** Defold C++ **File:** `res_light.h` **Source:** `engine/gamesys/src/dmsdk/gamesys/resources/res_light.h` **Include:** `dmsdk/gamesys/resources/res_light.h` Helper types and accessors for the light resource type (`.lightc`). ## API ### GetLightPrototype *Type:* FUNCTION Returns the dmRender::HLightPrototype handle created from the .lightc data. The pointer remains valid until the resource is released. **Parameters** - `res` (LightResource*) - Light resource **Returns** - `prototype` (dmRender::HLightPrototype*) - Prototype pointer ### LightResource *Type:* STRUCT This struct is an opaque handle managed by the engine. # Script {#apis:engine-gamesys-src-dmsdk-gamesys-script-h} **Namespace:** `dmScript` **Language:** C++ **Type:** Defold C++ **File:** `script.h` **Source:** `engine/gamesys/src/dmsdk/gamesys/script.h` **Include:** `dmsdk/gamesys/script.h` Built-in scripting functions. ## API ### CheckCollection *Type:* FUNCTION Get current gameobject's collection handle **Notes** - Works from both a .script/.gui_script **Parameters** - `L` (lua_State*) - lua state - `index` (int) - lua-arg **Returns** - `instance` (lua_State*) - gameobject instance ### CheckGOInstance *Type:* FUNCTION Get current game object instance Works in both gameobjects and gui scripts **Parameters** - `L` (lua_State*) - lua state **Returns** - `instance` (dmGameObject::HInstance) ### CheckGOInstance *Type:* FUNCTION Get gameobject instance The instance reference (url) at stack index "index" will be resolved to an instance. **Notes** - The function only accepts instances in "this" collection. Otherwise a lua-error will be raised. **Parameters** - `L` (lua_State*) - lua state - `index` (int) - lua-arg **Returns** - `instance` (dmGameObject::HInstance) - gameobject instance **Examples** How to get the position of a gameobject in a script extension ``` static int get_position(lua_State* L) { DM_LUA_STACK_CHECK(L, 3); dmGameObject::HInstance instance = dmScript::CheckGOInstance(L, 1); dmVMath::Point3 position = dmGameObject::GetPosition(instance); lua_pushnumber(L, position.getX()); lua_pushnumber(L, position.getY()); lua_pushnumber(L, position.getZ()); return 3; } ``` ### dmScript::CheckBuffer *Type:* FUNCTION Retrieve a LuaHBuffer from the supplied lua state. Check if the value in the supplied index on the lua stack is a LuaHBuffer and returns it. **Notes** - The dmBuffer::IsBufferValid is already called on the returned buffer **Parameters** - `L` (lua_State*) - lua state - `index` (int) - Index of the value **Returns** - `buffer` (LuaHBuffer*) - pointer to dmScript::LuaHBuffer ### dmScript::CheckBufferNoError *Type:* FUNCTION Retrieve a LuaHBuffer from the supplied lua state. Check if the value in the supplied index on the lua stack is a LuaHBuffer and returns it. **Notes** - Returns 0 on error. Does not invoke lua_error. - deprecated. Prefer ToBuffer() instead. - The dmBuffer::IsBufferValid is already called on the returned buffer **Parameters** - `L` (lua_State*) - lua state - `index` (int) - Index of the value **Returns** - `buffer` (LuaHBuffer*) - pointer to dmScript::LuaHBuffer or 0 if not valid ### dmScript::CheckBufferUnpack *Type:* FUNCTION Retrieve a HBuffer from the supplied lua state Check if the value in the supplied index on the lua stack is a LuaHBuffer and it's valid, returns the HBuffer. **Notes** - The dmBuffer::IsBufferValid is already called on the returned buffer **Parameters** - `L` (lua_State*) - lua state - `index` (int) - Index of the value **Returns** - `buffer` (dmBuffer::HBuffer) - buffer if valid, 0 otherwise ### dmScript::CheckBufferUnpackNoError *Type:* FUNCTION Retrieve a HBuffer from the supplied lua state Check if the value in the supplied index on the lua stack is a LuaHBuffer and it's valid, returns the HBuffer. **Notes** - The dmBuffer::IsBufferValid is already called on the returned buffer **Parameters** - `L` (lua_State*) - lua state - `index` (int) - Index of the value **Returns** - `buffer` (dmBuffer::HBuffer) - buffer if valid, 0 otherwise ### dmScript::IsBuffer *Type:* FUNCTION Check if the value is a dmScript::LuaHBuffer **Parameters** - `L` (lua_State*) - lua state - `index` (int) - Index of the value **Returns** - `boolean` (boolean) - True if value at index is a LuaHBuffer ### dmScript::LuaHBuffer *Type:* STRUCT Holds info about the buffer and who owns it. **Members** - `Union` - of - m_BufferRes [type:void*] A buffer resource - m_Buffer [type:dmBuffer::HBuffer] A buffer - `m_Buffer` (dmBuffer::HBuffer) - The buffer (or resource) - `m_Owner` (dmScript::LuaBufferOwnership) - What ownership the pointer has **Examples** See examples for dmScript::PushBuffer() ### dmScript::PushBuffer *Type:* FUNCTION Will increase the stack by 1. **Parameters** - `L` (lua_State*) - lua state - `buffer` (dmScript::LuaHBuffer) - buffer to push **Examples** How to push a buffer and give Lua ownership of the buffer (GC) ``` dmScript::LuaHBuffer luabuf(buffer, dmScript::OWNER_LUA); PushBuffer(L, luabuf); ``` How to push a buffer and keep ownership in C++ ``` dmScript::LuaHBuffer luabuf(buffer, dmScript::OWNER_C); PushBuffer(L, luabuf); ``` ### dmScript::ToBuffer *Type:* FUNCTION Retrieve a LuaHBuffer from the supplied lua state. Check if the value in the supplied index on the lua stack is a LuaHBuffer and returns it. **Notes** - Returns 0 on error. Does not invoke lua_error. - The dmBuffer::IsBufferValid is already called on the returned buffer **Parameters** - `L` (lua_State*) - lua state - `index` (int) - Index of the value **Returns** - `buffer` (LuaHBuffer*) - pointer to dmScript::LuaHBuffer or 0 if not valid ### GetComponentFromLua *Type:* FUNCTION Get component user data from a url. **Notes** - The object referenced by the url must be in the same collection as the caller. **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - index to argument (a url) - `component_type` (const char*) - E.g. "factoryc". The call will fail if the found component does not have the specified extension - `world` (dmGameObject::HComponentWorld*) - The world associated owning the component. May be 0 - `component` (dmGameObject::HComponent*) - The component data associated with the url. May be 0 - `url` (dmMessage::URL*) - The resolved url. May be 0 ### LuaBufferOwnership *Type:* ENUM Buffer ownership. - OWNER_C - m_Buffer is owned by C side, should not be destroyed when GCed - OWNER_LUA - m_Buffer is owned by Lua side, will be destroyed when GCed - OWNER_RES - m_Buffer not used, has a reference to a buffer resource instead. m_BufferRes is owned by C side, will be released when GCed **Members** - `dmScript::OWNER_C` - `dmScript::OWNER_LUA` - `dmScript::OWNER_RES` # Graphics {#apis:engine-graphics-src-dmsdk-graphics-graphics-h} **Namespace:** `dmGraphics` **Language:** C++ **Type:** Defold C++ **File:** `graphics.h` **Source:** `engine/graphics/src/dmsdk/graphics/graphics.h` **Include:** `dmsdk/graphics/graphics.h` Graphics API ## API ### AdapterFamily *Type:* ENUM Graphics adapter family. Identifies the type of graphics backend used by the rendering system **Members** - `ADAPTER_FAMILY_NONE` - No adapter detected. Used as an error state or uninitialized value - `ADAPTER_FAMILY_NULL` - Null (dummy) backend. Used for headless operation, testing, or environments where rendering output is not required - `ADAPTER_FAMILY_OPENGL` - OpenGL desktop backend. Common on Windows, macOS and Linux systems - `ADAPTER_FAMILY_OPENGLES` - OpenGL ES backend. Primarily used on mobile devices (Android, iOS), as well as WebGL (browser) - `ADAPTER_FAMILY_VULKAN` - Vulkan backend. Cross-platform modern graphics API with explicit control over GPU resources and multithreading - `ADAPTER_FAMILY_VENDOR` - Vendor-specific backend. A placeholder for proprietary or experimental APIs tied to a particular GPU vendor. - `ADAPTER_FAMILY_WEBGPU` - WebGPU backend. Modern web graphics API designed as the successor to WebGL - `ADAPTER_FAMILY_DIRECTX` - DirectX backend. Microsoft’s graphics API used on Windows and Xbox ### AddVertexStream *Type:* FUNCTION Adds a stream to a vertex stream declaration **Parameters** - `name` (const char*) - the name of the stream - `size` (uint32_t) - the size of the stream, i.e number of components - `type` (dmGraphics::Type) - the data type of the stream - `normalize` (bool) - true if the stream should be normalized in the 0..1 range ### AddVertexStream *Type:* FUNCTION Adds a stream to a vertex stream declaration **Parameters** - `name_hash` (dmhash_t) - the name hash of the stream - `size` (uint32_t) - the size of the stream, i.e number of components - `type` (dmGraphics::Type) - the data type of the stream - `normalize` (bool) - true if the stream should be normalized in the 0..1 range ### AttachmentOp *Type:* ENUM Defines how an attachment should be treated at the start and end of a render pass **Members** - `ATTACHMENT_OP_DONT_CARE` - Ignore existing content, no guarantees about the result - `ATTACHMENT_OP_LOAD` - Preserve the existing contents of the attachment - `ATTACHMENT_OP_STORE` - Store the attachment’s results after the pass finishes - `ATTACHMENT_OP_CLEAR` - Clear the attachment to a predefined value at the beginning of the pass ### BeginFrame *Type:* FUNCTION Begins frame rendering. Prepares the graphics context for rendering a new frame. This should be called at the start of each frame. **Parameters** - `context` (dmGraphics::HContext) - Graphics context ### BlendFactor *Type:* ENUM Blend factors for color blending. Defines how source and destination colors are combined **Members** - `BLEND_FACTOR_ZERO` - Always use 0.0 - `BLEND_FACTOR_ONE` - Always use 1.0 - `BLEND_FACTOR_SRC_COLOR` - Use source color - `BLEND_FACTOR_ONE_MINUS_SRC_COLOR` - Use (1 - source color) - `BLEND_FACTOR_DST_COLOR` - Use destination color - `BLEND_FACTOR_ONE_MINUS_DST_COLOR` - Use (1 - destination color) - `BLEND_FACTOR_SRC_ALPHA` - Use source alpha - `BLEND_FACTOR_ONE_MINUS_SRC_ALPHA` - Use (1 - source alpha) - `BLEND_FACTOR_DST_ALPHA` - Use destination alpha - `BLEND_FACTOR_ONE_MINUS_DST_ALPHA` - Use (1 - destination alpha) - `BLEND_FACTOR_SRC_ALPHA_SATURATE` - Use min(srcAlpha, 1 - dstAlpha) - `BLEND_FACTOR_CONSTANT_COLOR` - `BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR` - `BLEND_FACTOR_CONSTANT_ALPHA` - `BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA` ### BufferAccess *Type:* ENUM **Members** - `BUFFER_ACCESS_READ_ONLY` - `BUFFER_ACCESS_WRITE_ONLY` - `BUFFER_ACCESS_READ_WRITE` ### BufferUsage *Type:* ENUM Buffer usage hints. Indicates how often the data in a buffer will be updated. Helps the driver optimize memory placement **Members** - `BUFFER_USAGE_STREAM_DRAW` - Updated every frame, used once (e.g. dynamic geometry) - `BUFFER_USAGE_DYNAMIC_DRAW` - Updated occasionally, used many times - `BUFFER_USAGE_STATIC_DRAW` - Set once, used many times (e.g. meshes, textures). Preferred for buffers that never change ### Clear *Type:* FUNCTION Clears the render target buffers. Fills the specified buffers with predefined values. Commonly used at the beginning of a frame to clear the screen to a specific color and depth. **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `flags` (uint32_t) - Bitmask specifying which buffers to clear (BUFFER_TYPE_*) - `red` (uint8_t) - Red component value (0-255) - `green` (uint8_t) - Green component value (0-255) - `blue` (uint8_t) - Blue component value (0-255) - `alpha` (uint8_t) - Alpha component value (0-255) - `depth` (float) - Depth value to clear depth buffer to - `stencil` (uint32_t) - Stencil value to clear stencil buffer to ### CloseWindow *Type:* FUNCTION Closes the window associated with the graphics context. If a window is open, this will close it and clean up associated resources. **Parameters** - `context` (dmGraphics::HContext) - Graphics context ### CompareFunc *Type:* ENUM Depth and alpha test comparison functions. Defines how incoming values are compared against stored ones **Members** - `COMPARE_FUNC_NEVER` - Never passes. - `COMPARE_FUNC_LESS` - Passes if incoming < stored - `COMPARE_FUNC_LEQUAL` - Passes if incoming <= stored - `COMPARE_FUNC_GREATER` - Passes if incoming > stored - `COMPARE_FUNC_GEQUAL` - Passes if incoming >= stored - `COMPARE_FUNC_EQUAL` - Passes if incoming == stored - `COMPARE_FUNC_NOTEQUAL` - Passes if incoming != stored - `COMPARE_FUNC_ALWAYS` - Always passes (ignores stored values) ### ContextParams *Type:* STRUCT Graphics context creation parameters. Defines the configuration for creating a new graphics context. This structure is used when initializing the graphics system and specifies window association, job system context, texture filtering defaults, resolution, memory limits, and various debugging/validation options. **Members** - `m_Window` (dmPlatform::HWindow) - Platform window handle to associate with the graphics context - `m_JobContext` (dmJobSystem::HJobContext) - Job system context for asynchronous operations - `m_DefaultTextureMinFilter` (dmGraphics::TextureFilter) - Default minification filter for textures - `m_DefaultTextureMagFilter` (dmGraphics::TextureFilter) - Default magnification filter for textures - `m_Width` (uint32_t) - Initial width of the rendering surface - `m_Height` (uint32_t) - Initial height of the rendering surface - `m_GraphicsMemorySize` (uint32_t) - Maximum allowed graphics memory in bytes (0 for default/unlimited) (Switch) - `m_SwapInterval` (uint32_t) - Vertical synchronization interval (1 for 60Hz, 2 for 30Hz, etc.) (Default = 1) - `m_GraphicsApiVersionMajorHint` (uint16_t) - Requested graphics API major version hint. A value of 0 lets the platform use its default. - `m_GraphicsApiVersionMinorHint` (uint16_t) - Requested graphics API minor version hint. - `m_VerifyGraphicsCalls` (bool) - Enable API call verification for debugging - `m_PrintDeviceInfo` (bool) - Print graphics device information at startup - `m_UseValidationLayers` (bool) - Enable validation layers for debugging (Vulkan/DirectX 12 only) ### DeleteContext *Type:* FUNCTION Destroys a graphics context. Cleans up all resources associated with the graphics context. The context becomes invalid after this call. **Parameters** - `context` (dmGraphics::HContext) - Graphics context to destroy ### DeleteIndexBuffer *Type:* FUNCTION Delete the index buffer **Parameters** - `buffer` (dmGraphics::HIndexBuffer) - the index buffer ### DeleteProgram *Type:* FUNCTION Destroys a shader program and frees associated resources. Cleans up GPU memory and resources associated with the program handle. The handle becomes invalid after this call. **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `program` (dmGraphics::HProgram) - Program handle to destroy ### DeleteRenderTarget *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `render_target` (dmGraphics::HRenderTarget) ### DeleteTexture *Type:* FUNCTION Delete texture **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `texture` (dmGraphics::HTexture) - Texture handle ### DeleteVertexBuffer *Type:* FUNCTION Delete vertex buffer **Parameters** - `buffer` (dmGraphics::HVertexBuffer) - the buffer ### DeleteVertexDeclaration *Type:* FUNCTION Delete vertex declaration **Parameters** - `vertex_declaration` (dmGraphics::HVertexDeclaration) - the vertex declaration ### DeleteVertexStreamDeclaration *Type:* FUNCTION Delete vertex stream declaration **Parameters** - `stream_declaration` (dmGraphics::HVertexStreamDeclaration) - the vertex stream declaration ### DisableProgram *Type:* FUNCTION Deactivates the currently bound shader program. Unbinds any active program from the graphics pipeline, returning to the default state where no custom shader program is active. **Parameters** - `context` (dmGraphics::HContext) - Graphics context ### DisableState *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `state` (dmGraphics::State) - Render state ### DisableTexture *Type:* FUNCTION Disable a texture bound to a texture unit. Unbinds the given texture handle from the specified unit, releasing the association in the graphics pipeline. This is useful to prevent unintended reuse of textures, or to free up texture units for other bindings. **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `unit` (uint32_t) - Texture unit index to disable. Must match the one previously used in dmGraphics::EnableTexture - `texture` (dmGraphics::HTexture) - Handle to the texture object to disable ### DisableVertexBuffer *Type:* FUNCTION Unbinds a vertex buffer from the graphics pipeline. Removes the association between a vertex buffer and its binding index, freeing up the binding slot for other buffers. **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `vertex_buffer` (dmGraphics::HVertexBuffer) - Vertex buffer handle to unbind ### DisableVertexDeclaration *Type:* FUNCTION Unbinds a vertex declaration from the graphics pipeline. Removes the association between a vertex declaration and its binding index, freeing up the binding slot for other declarations. **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `vertex_declaration` (dmGraphics::HVertexDeclaration) - Vertex declaration handle to unbind ### Draw *Type:* FUNCTION Draws non-indexed primitives. Renders geometry using vertex data directly from the bound vertex buffers without index buffer indirection. The vertices are processed sequentially from the specified starting point. **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `prim_type` (dmGraphics::PrimitiveType) - Type of primitives to draw - `first` (uint32_t) - Index of the first vertex to draw - `count` (uint32_t) - Number of vertices to draw - `instance_count` (uint32_t) - Number of instances to draw (for instanced rendering) ### EnableProgram *Type:* FUNCTION Activates a shader program for rendering. Binds the specified program to the graphics pipeline, making it the active program for all subsequent rendering operations until another program is activated or disabled. **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `program` (dmGraphics::HProgram) - Program handle to activate ### EnableState *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `state` (dmGraphics::State) - Render state ### EnableTexture *Type:* FUNCTION Enable and bind a texture to a texture unit. Associates a texture object with a specific texture unit in the graphics context, making it available for sampling in shaders. Multiple textures can be active simultaneously by binding them to different units. The shader must reference the correct unit (via sampler uniform) to access the bound texture **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `unit` (uint32_t) - Texture unit index to bind the texture to. Valid range depends on GPU capabilities (commonly 0–15 for at least 16 texture units) - `id_index` (uint8_t) - Index for internal tracking or binding variation. Typically used when multiple texture IDs are managed within the same unit (e.g. array textures or multi-bind) - `texture` (dmGraphics::HTexture) - Handle to the texture object to enable and bind ### EnableVertexBuffer *Type:* FUNCTION Binds a vertex buffer for rendering. Associates a vertex buffer with a specific binding index in the graphics pipeline. The buffer provides the actual vertex data that will be processed according to the active vertex declaration for that binding index. **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `vertex_buffer` (dmGraphics::HVertexBuffer) - Vertex buffer handle - `binding_index` (uint32_t) - Binding index to associate with this buffer ### EnableVertexDeclaration *Type:* FUNCTION Binds a vertex declaration for rendering. Associates a vertex declaration with a specific binding index in the graphics pipeline. The declaration defines how vertex data is interpreted and laid out in memory. **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `vertex_declaration` (dmGraphics::HVertexDeclaration) - Vertex declaration handle - `binding_index` (uint32_t) - Binding index to associate with this declaration - `base_offset` (uint32_t) - Byte offset to add to all vertex attribute pointers - `program` (dmGraphics::HProgram) - Shader program to use with this declaration ### FaceWinding *Type:* ENUM **Members** - `FACE_WINDING_CCW` - `FACE_WINDING_CW` ### Finalize *Type:* FUNCTION Finalizes the graphics system. Cleans up global graphics resources and shuts down the graphics system. This should be called when the application is exiting. ### FindUniformLocation *Type:* FUNCTION Finds the location of a uniform variable in a shader program by name hash. Returns the uniform location that can be used with other uniform-setting functions. This is the preferred method when the uniform name is known at compile time as it avoids runtime string hashing. **Parameters** - `program` (dmGraphics::HProgram) - Shader program handle - `name_hash` (dmhash_t) - Hash of the uniform variable name **Returns** - `location` (dmGraphics::HUniformLocation) - Uniform location handle, or INVALID_UNIFORM_LOCATION if not found ### FindUniformLocation *Type:* FUNCTION Finds the location of a uniform variable in a shader program by name string. Returns the uniform location that can be used with other uniform-setting functions. This method is useful when the uniform name is only known at runtime. **Parameters** - `program` (dmGraphics::HProgram) - Shader program handle - `name` (const char*) - Name of the uniform variable **Returns** - `location` (dmGraphics::HUniformLocation) - Uniform location handle, or INVALID_UNIFORM_LOCATION if not found ### Flip *Type:* FUNCTION Flips screen buffers. Presents the rendered frame to the display. This should be called at the end of each frame after all rendering is complete. **Parameters** - `context` (dmGraphics::HContext) - Graphics context ### GetAdapterFamily *Type:* FUNCTION Gets the adapter family from a string name. Converts a string identifier to the corresponding AdapterFamily enum value. **Parameters** - `adapter_name` (const char*) - String name of the adapter (e.g., "opengl", "vulkan") **Returns** - `family` (dmGraphics::AdapterFamily) - Corresponding adapter family enum value ### GetDisplayScaleFactor *Type:* FUNCTION Get the scale factor of the display. The display scale factor is usally 1.0 but will for instance be 2.0 on a macOS Retina display. **Parameters** - `context` (dmGraphics::HContext) - Graphics context **Returns** - `scale_factor` (float) - Display scale factor ### GetHeight *Type:* FUNCTION Returns the specified height of the opened window, which might differ from the actual window width. **Parameters** - `context` (dmGraphics::HContext) - Graphics context **Returns** - `height` (uint32_t) - Specified height of the window. If no window is opened, 0 is always returned. ### GetInstalledAdapterFamily *Type:* FUNCTION Get installed graphics adapter family **Returns** - `family` (dmGraphics::AdapterFamily) - Installed adapter family ### GetInstalledContext *Type:* FUNCTION **Returns** - `context` (dmGraphics::HContext) - Installed graphics context ### GetMaxElementsIndices *Type:* FUNCTION Get the max number of indices allowed by the system in an index buffer **Parameters** - `context` (dmGraphics::HContext) - the context **Returns** - `count` (uint32_t) - the count ### GetMaxElementsVertices *Type:* FUNCTION Get the max number of vertices allowed by the system in a vertex buffer **Parameters** - `context` (dmGraphics::HContext) - the context **Returns** - `count` (uint32_t) - the count ### GetMaxTextureSize *Type:* FUNCTION Get maximum supported size in pixels of non-array texture **Parameters** - `context` (dmGraphics::HContext) - Graphics context **Returns** - `max_texture_size` (uint32_t) - Maximum texture size supported by GPU ### GetNumSupportedExtensions *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - the context **Returns** - `count` (uint32_t) - the number of supported extensions ### GetNumTextureHandles *Type:* FUNCTION Get how many platform-dependent texture handle used for engine texture handle. Applicable only for OpenGL/ES backend. All other backends return 1. **Parameters** - `context` (dmGraphics::Context) - Graphics context - `texture` (dmGraphics::HTexture) - Texture handle **Returns** - `handles_amount` (uint8_t) - Platform-dependent handles amount ### GetOriginalTextureHeight *Type:* FUNCTION Get texture original (before uploading to GPU) height **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `texture` (dmGraphics::HTexture) - Texture handle **Returns** - `original_height` (uint16_t) ### GetOriginalTextureWidth *Type:* FUNCTION Get texture original (before uploading to GPU) width **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `texture` (dmGraphics::HTexture) - Texture handle **Returns** - `original_width` (uin16_t) - Texture's original width ### GetPipelineState *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context **Returns** - `pipeline_state` (dmGraphics::PipelineState) ### GetRenderTargetAttachment *Type:* FUNCTION Get the attachment texture from a render target. Returns zero if no such attachment texture exists. **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `render_target` (dmGraphics::HRenderTarget) - the render target - `attachment_type` (dmGraphics::RenderTargetAttachment) - the attachment to get **Returns** - `attachment` (dmGraphics::HTexture) - the attachment texture ### GetRenderTargetSize *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `render_target` (dmGraphics::HRenderTarget) - `buffer_type` (dmGraphics::BufferType) - `width` (uint32_t&) - `height` (uint32_t&) ### GetRenderTargetTexture *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `render_target` (dmGraphics::HRenderTarget) - `buffer_type` (dmGraphics::BufferType) **Returns** - `render_target_texture` (dmGraphics::HTexture) ### GetSupportedExtension *Type:* FUNCTION get the supported extension **Parameters** - `context` (dmGraphics::HContext) - the context - `index` (uint32_t) - the index of the extension **Returns** - `extension` (const char*) - the extension. 0 if index was out of bounds ### GetTextureDepth *Type:* FUNCTION Get texture depth. applicable for 3D and cube map textures **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `texture` (dmGraphics::HTexture) - Texture handle **Returns** - `depth` (uint16_t) - Texture's depth ### GetTextureFormatLiteral *Type:* FUNCTION Get string representation of texture format **Parameters** - `format` (dmGraphics::TextureFormat) - Texture format **Returns** - `literal_format` (const char*) - String representation of format ### GetTextureHandle *Type:* FUNCTION Get the native graphics API texture object from an engine texture handle. This depends on the graphics backend and is not guaranteed to be implemented on the currently running adapter. **Parameters** - `texture` (dmGraphics::HTexture) - the texture handle - `out_handle` (void**) - a pointer to where the raw object should be stored **Returns** - `handle_result` (dmGraphics::HandleResult) - the result of the query ### GetTextureHeight *Type:* FUNCTION Get texture height **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `texture` (dmGraphics::HTexture) - Texture handle **Returns** - `height` (uint16_t) - Texture's height ### GetTextureMipmapCount *Type:* FUNCTION Get texture mipmap count **Parameters** - `context` (dmGraphice::HContext) - Graphics context - `texture` (dmGraphics::HTexture) - Texture handle **Returns** - `count` (uint8_t) - Texture mipmap count ### GetTextureResourceSize *Type:* FUNCTION Get approximate size of how much memory texture consumes **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `texture` (dmGraphics::HTexture) - Texture handle **Returns** - `data_size` (uint32_t) - Resource data size in bytes ### GetTextureStatusFlags *Type:* FUNCTION Get status of texture **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `texture` (dmGraphics::HTexture) - Texture handle **Returns** - `flags` (dmGraphics::TextureStatusFlags) - Enumerated status bit flags ### GetTextureType *Type:* FUNCTION Get texture type **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `texture` (dmGraphics::HTexture) - Texture handle **Returns** - `type` (dmGraphics::TextureType) - Texture type ### GetTextureTypeLiteral *Type:* FUNCTION Get string representation of texture type **Parameters** - `texture_type` (dmGraphics::TextureType) - Texture type **Returns** - `literal_type` (const char*) - String representation of type ### GetTextureUsageHintFlags *Type:* FUNCTION Query usage hint flags for a texture. Retrieves the bitwise usage flags that were assigned to a texture when it was created. These flags indicate the intended role(s) of the texture in the rendering pipeline and allow the graphics backend to apply optimizations or enforce restrictions **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `texture` (dmGraphics::HTexture) - Texture handle **Returns** - `flags` (uint32_t) - A bitwise OR of usage flags describing how the texture may be used. Applications can test specific flags using bitmask operations ### GetTextureWidth *Type:* FUNCTION Get texture width **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `texture` (dmGraphics::HTexture) - Texture handle **Returns** - `width` (uint16_t) - Texture's width ### GetVertexStreamOffset *Type:* FUNCTION Get the physical offset into the vertex data for a particular stream **Parameters** - `vertex_declaration` (dmGraphics::HVertexDeclaration) - the vertex declaration - `name_hash` (dmhash_t) - the name hash of the vertex stream (as passed into AddVertexStream()) **Returns** - `Offset` - in bytes into the vertex or INVALID_STREAM_OFFSET if not found ### GetViewport *Type:* FUNCTION Get viewport's parameters **Parameters** - `context` (dmGraphics::HContext) - the context - `x` (int32_t) - x-coordinate of the viewport's origin - `y` (int32_t) - y-coordinate of the viewport's origin - `width` (uint32_t) - viewport's width - `height` (uint32_t) - viewport's height ### GetWidth *Type:* FUNCTION Returns the specified width of the opened window, which might differ from the actual window width. **Parameters** - `context` (dmGraphics::HContext) - Graphics context **Returns** - `width` (uint32_t) - Specified width of the window. If no window is opened, 0 is always returned. ### GetWindowHeight *Type:* FUNCTION Return the height of the opened window, if any. **Parameters** - `context` (dmGraphics::HContext) - Graphics context **Returns** - `window_height` (uint32_t) - Height of the window. If no window is opened, 0 is always returned ### GetWindowWidth *Type:* FUNCTION Return the width of the opened window, if any. **Parameters** - `context` (dmGraphics::HContext) - Graphics context **Returns** - `window_width` (uint32_t) - Width of the window. If no window is opened, 0 is always returned ### HandleResult *Type:* ENUM Function's call result code **Members** - `HANDLE_RESULT_OK` - The function's call succeeded and returned a valid result - `HANDLE_RESULT_NOT_AVAILABLE` - The function is not supported by the current graphics backend - `HANDLE_RESULT_ERROR` - An error occurred while function call ### HContext *Type:* TYPEDEF Context handle ### HIndexBuffer *Type:* TYPEDEF Index buffer handle ### HProgram *Type:* TYPEDEF Program handle ### HRenderTarget *Type:* TYPEDEF Rendertarget handle ### HStorageBuffer *Type:* TYPEDEF Storage buffer handle ### HTexture *Type:* TYPEDEF Texture handle ### HUniformLocation *Type:* TYPEDEF Uniform location handle ### HVertexBuffer *Type:* TYPEDEF Vertex buffer handle ### HVertexDeclaration *Type:* TYPEDEF Vertex declaration handle ### HVertexStreamDeclaration *Type:* TYPEDEF Vertex stream declaration handle ### IndexBufferFormat *Type:* ENUM Index buffer element types. Defines the integer size used for vertex indices **Members** - `INDEXBUFFER_FORMAT_16` - 16-bit unsigned integers (max 65535 vertices) - `INDEXBUFFER_FORMAT_32` - 32-bit unsigned integers (supports larger meshes) ### InstallAdapter *Type:* FUNCTION Installs a graphics adapter. Initializes the specified graphics backend (OpenGL, Vulkan, etc.). This must be called before creating any graphics context. **Parameters** - `family` (dmGraphics::AdapterFamily) - Graphics adapter family to install **Returns** - `success` (bool) - True if the adapter was successfully installed, false otherwise ### INVALID_PROGRAM_HANDLE *Type:* CONSTANT Invalid program handle constant. Used to represent an uninitialized or invalid program handle. Can be used to check if program creation or loading failed. ### INVALID_STREAM_OFFSET *Type:* CONSTANT Invalid stream offset ### INVALID_UNIFORM_LOCATION *Type:* CONSTANT Invalid uniform location constant. Used to represent an uninitialized or invalid uniform location. Can be used to check if uniform location lookup failed. ### IsExtensionSupported *Type:* FUNCTION check if an extension is supported **Parameters** - `context` (dmGraphics::HContext) - the context - `extension` (const char*) - the extension. **Returns** - `result` (bool) - true if the extension was supported ### IsIndexBufferFormatSupported *Type:* FUNCTION Check if the index format is supported **Parameters** - `context` (dmGraphics::HContext) - the context - `format` (dmGraphics::IndexBufferFormat) - the format - `result` (bool) - true if the format is supoprted ### IsTextureFormatSupported *Type:* FUNCTION check if a specific texture format is supported **Parameters** - `context` (dmGraphics::HContext) - the context - `format` (dmGraphics::TextureFormat) - the texture format. **Returns** - `result` (bool) - true if the texture format was supported ### MAX_BUFFER_COLOR_ATTACHMENTS *Type:* CONSTANT Max buffer color attachments ### NewContext *Type:* FUNCTION Creates a new graphics context. Initializes the graphics system with the specified parameters. Only one graphics context can be active at a time. **Parameters** - `params` (const dmGraphics::ContextParams&) - Context creation parameters **Returns** - `context` (dmGraphics::HContext) - New graphics context handle, or null on failure ### NewIndexBuffer *Type:* FUNCTION Create new index buffer with initial data **Notes** - The caller need to track if the indices are 16 or 32 bit. **Parameters** - `context` (dmGraphics::HContext) - the context - `size` (uint32_t) - the size of the buffer (in bytes). May be 0 - `data` (void*) - the data - `buffer_usage` (dmGraphics::BufferUsage) - the usage **Returns** - `buffer` (dmGraphics::HIndexBuffer) - the index buffer ### NewProgram *Type:* FUNCTION Creates a new shader program from a shader description. Compiles and links shader sources defined in the ShaderDesc into a GPU program. Returns a program handle that can be used for rendering. **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `ddf` (dmGraphics::ShaderDesc*) - Shader description containing source code and parameters - `error_buffer` (char*) - Buffer to receive error messages (can be null) - `error_buffer_size` (uint32_t) - Size of the error buffer **Returns** - `program` (dmGraphics::HProgram) - New program handle, or INVALID_PROGRAM_HANDLE on failure ### NewRenderTarget *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `buffer_type_flags` (uint32_t) - `params` (dmGraphics::const RenderTargetCreationParams) **Returns** - `render_target` (dmGraphics::HRenderTarget) - Newly created render target ### NewTexture *Type:* FUNCTION Create new texture **Parameters** - `context` (HContext) - Graphics context - `params` (const dmGraphics::TextureCreationParams&) - Creation parameters **Returns** - `texture_handle` (dmGraphics::HTexture) - Opaque texture handle ### NewVertexBuffer *Type:* FUNCTION Create new vertex buffer with initial data **Parameters** - `context` (dmGraphics::HContext) - the context - `size` (uint32_t) - the size of the buffer (in bytes). May be 0 - `data` (void*) - the data - `buffer_usage` (dmGraphics::BufferUsage) - the usage **Returns** - `buffer` (dmGraphics::HVertexBuffer) - the vertex buffer ### NewVertexDeclaration *Type:* FUNCTION Create new vertex declaration from a vertex stream declaration **Parameters** - `context` (dmGraphics::HContext) - the context - `stream_declaration` (dmGraphics::HVertexStreamDeclaration) - the vertex stream declaration **Returns** - `declaration` (dmGraphics::HVertexDeclaration) - the vertex declaration ### NewVertexDeclaration *Type:* FUNCTION Create new vertex declaration from a vertex stream declaration and an explicit stride value, where the stride is the number of bytes between each consecutive vertex in a vertex buffer **Parameters** - `context` (dmGraphics::HContext) - the context - `stream_declaration` (dmGraphics::HVertexStreamDeclaration) - the vertex stream declaration - `stride` (uint32_t) - the stride between the start of each vertex (in bytes) **Returns** - `declaration` (dmGraphics::HVertexDeclaration) - the vertex declaration ### NewVertexStreamDeclaration *Type:* FUNCTION Create new vertex stream declaration. A stream declaration contains a list of vertex streams that should be used to create a vertex declaration from. **Parameters** - `context` (dmGraphics::HContext) - the context **Returns** - `declaration` (dmGraphics::HVertexStreamDeclaration) - the vertex declaration ### NewVertexStreamDeclaration *Type:* FUNCTION Create new vertex stream declaration. A stream declaration contains a list of vertex streams that should be used to create a vertex declaration from. **Parameters** - `context` (dmGraphics::HContext) - the context - `step_function` (dmGraphics::VertexStepFunction) - the vertex step function to use **Returns** - `declaration` (dmGraphics::HVertexStreamDeclaration) - the vertex declaration ### PrimitiveType *Type:* ENUM Primitive drawing modes. Defines how vertex data is assembled into primitives **Members** - `PRIMITIVE_LINES` - Each pair of vertices forms a line - `PRIMITIVE_TRIANGLES` - Each group of 3 vertices forms a triangle - `PRIMITIVE_TRIANGLE_STRIP` - Connected strip of triangles (shares vertices) ### ReadPixels *Type:* FUNCTION Read frame buffer pixels in BGRA format **Parameters** - `context` (dmGraphics::HContext) - the context - `x` (int32_t) - x-coordinate of the starting position - `y` (int32_t) - y-coordinate of the starting position - `width` (uint32_t) - width of the region - `height` (uint32_t) - height of the region - `buffer` (void*) - buffer to read to - `buffer_size` (uint32_t) - buffer size ### RenderTargetAttachment *Type:* ENUM Attachment points for render targets **Members** - `ATTACHMENT_COLOR` - A color buffer attachment (used for rendering visible output) - `ATTACHMENT_DEPTH` - A depth buffer attachment (used for depth testing) - `ATTACHMENT_STENCIL` - A stencil buffer attachment (used for stencil operations) ### RepackRGBToRGBA *Type:* FUNCTION **Parameters** - `num_pixels` (uint32_t) - `rgb` (uint8_t*) - `rgba` (uint8_t*) ### SetBlendFunc *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `source_factor` (gmGraphics::BlendFactor) - `destination_factor` (dmGraphics::BlendFactor) ### SetColorMask *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `red` (bool) - `green` (bool) - `blue` (bool) - `alpha` (bool) ### SetCullFace *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `face_type` (dmGraphics::FaceType) ### SetDepthFunc *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `func` (dmGraphics::CompareFunc) ### SetDepthMask *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `enable_mask` (bool) ### SetIndexBufferData *Type:* FUNCTION Set index buffer data **Parameters** - `buffer` (dmGraphics::HIndexBuffer) - the buffer - `size` (uint32_t) - the size of the buffer (in bytes). May be 0 - `data` (void*) - the data - `buffer_usage` (dmGraphics::BufferUsage) - the usage ### SetIndexBufferSubData *Type:* FUNCTION Set subset of index buffer data **Parameters** - `buffer` (dmGraphics::HVertexBuffer) - the buffer - `offset` (uint32_t) - the offset into the desination buffer (in bytes) - `size` (uint32_t) - the size of the buffer (in bytes). May be 0 - `data` (void*) - the data ### SetRenderTarget *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `render_target` (dmGraphics::HRenderTarget) - `transient_buffer_types` (uint32_t) ### SetRenderTargetSize *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `render_target` (dmGraphics::HRenderTarget) - `width` (uint32_t) - `height` (uint32_t) ### SetSampler *Type:* FUNCTION Binds a texture sampler to a texture unit. Associates a texture with a specific sampler uniform in the shader, allowing the shader to access the texture data during rendering. **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `location` (dmGraphics::HUniformLocation) - Uniform location of the sampler - `unit` (int32_t) - Texture unit index to bind to ### SetStencilFunc *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `func` (dmGraphics::CompareFunc) - `ref` (uint32_t) - `mask` (uint32_t) ### SetStencilFuncSeparate *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `face_type` (dmGraphics::FaceType) - `func` (dmGraphics::CompareFunc) - `ref` (uint32_t) - `mask` (uint32_t) ### SetStencilMask *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `mask` (uint32_t) ### SetStencilOp *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `sfail` (dmGraphics::StencilOp) - `dpfail` (dmGraphics::StencilOp) - `dppass` (dmGraphics::StencilOp) ### SetStencilOpSeparate *Type:* FUNCTION **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `face_type` (dmGraphics::FaceType) - `sfail` (dmGraphics::StencilOp) - `dpfail` (dmGraphics::StencilOp) - `dppass` (dmGraphics::StencilOp) ### SetTexture *Type:* FUNCTION Set texture data. For textures of type TEXTURE_TYPE_CUBE_MAP it's assumed that 6 mip-maps are present contiguously in memory with stride m_DataSize **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `texture` (dmGraphics::HTexture) - Texture handle - `params` (const dmGraphics::TextureParams&) ### SetTextureAsync *Type:* FUNCTION Set texture data asynchronously. For textures of type TEXTURE_TYPE_CUBE_MAP it's assumed that 6 mip-maps are present contiguously in memory with stride m_DataSize **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `texture` (dmGraphics::HTexture) - Texture handle - `params` (const dmGraphics::TextureParams&) - Texture parameters. Texture will be recreated if parameters differ from creation parameters - `callback` (dmGraphics::SetTextureAsyncCallback) - Completion callback - `user_data` (void*) - User data that will be passed to completion callback ### SetTextureAsyncCallback *Type:* TYPEDEF Function called when a texture has been set asynchronously **Parameters** - `texture` (dmGraphics::HTexture) - Texture handle - `user_data` (void*) - User data that will be passed to the SetTextureAsyncCallback ### SetTextureParams *Type:* FUNCTION Set texture parameters **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `texture` (dmGraphics::HTexture) - Texture handle - `min_filter` (dmGraphics::TextureFilter) - Minification filter type - `mag_filter` (dmGraphics::TextureFilter) - Magnification filter type - `uwrap` (dmGraphics::TextureWrap) - Wrapping mode for the U (X) texture coordinate. - `vwrap` (dmGraphics::TextureWrap) - Wrapping mode for the V (Y) texture coordinate - `max_anisotropy` (float) ### SetVertexBufferData *Type:* FUNCTION Set vertex buffer data **Parameters** - `buffer` (dmGraphics::HVertexBuffer) - the buffer - `size` (uint32_t) - the size of the buffer (in bytes). May be 0 - `data` (void*) - the data - `buffer_usage` (dmGraphics::BufferUsage) - the usage ### SetVertexBufferSubData *Type:* FUNCTION Set subset of vertex buffer data **Parameters** - `buffer` (dmGraphics::HVertexBuffer) - the buffer - `offset` (uint32_t) - the offset into the desination buffer (in bytes) - `size` (uint32_t) - the size of the buffer (in bytes). May be 0 - `data` (void*) - the data ### SetViewport *Type:* FUNCTION Sets the viewport for rendering. Defines the affine transformation from normalized device coordinates to window coordinates. This affects all subsequent rendering operations. **Parameters** - `context` (dmGraphics::HContext) - Graphics context - `x` (int32_t) - X coordinate of the viewport's origin (in pixels) - `y` (int32_t) - Y coordinate of the viewport's origin (in pixels) - `width` (int32_t) - Width of the viewport (in pixels) - `height` (int32_t) - Height of the viewport (in pixels) ### ShaderDesc *Type:* STRUCT Shader program description (from graphics_ddf.h) ### StencilOp *Type:* ENUM Stencil test actions. Defines what happens to a stencil buffer value depending on the outcome of the stencil/depth test. **Members** - `STENCIL_OP_KEEP` - Keep the current stencil value - `STENCIL_OP_ZERO` - Set stencil value to 0 - `STENCIL_OP_REPLACE` - Replace stencil value with reference value - `STENCIL_OP_INCR` - Increment stencil value (clamps at max) - `STENCIL_OP_INCR_WRAP` - Increment stencil value, wrapping around - `STENCIL_OP_DECR` - Decrement stencil value (clamps at 0) - `STENCIL_OP_DECR_WRAP` - Decrement stencil value, wrapping around - `STENCIL_OP_INVERT` - Bitwise invert stencil value ### TextureCreationParams *Type:* STRUCT Texture creation parameters. Defines how a texture is created, initialized, and used. This structure is typically passed when allocating GPU memory for a new texture. It controls dimensions, format, layering, mipmapping, and intended usage. **Members** - `m_Type` (dmGraphics::TextureType) - Texture type. Defines the dimensionality and interpretation of the texture (2D, 3D, cube map, array) - `m_Width` (uint16_t) - Width of the texture in pixels at the base mip level - `m_Height` (uint16_t) - Height of the texture in pixels at the base mip level - `m_Depth` (uint16_t) - Depth of the texture. Used for 3D textures or texture arrays. For standard 2D textures, this is typically `1` - `m_OriginalWidth` (uint16_t) - Width of the original source data before scaling or compression - `m_OriginalHeight` (uint16_t) - Height of the original source data before scaling or compression - `m_OriginalDepth` (uint16_t) - Depth of the original source data - `m_LayerCount` (uint8_t) - Number of layers in the texture. Used for array textures (`TEXTURE_TYPE_2D_ARRAY`). For standard 2D textures, this is `1` - `m_MipMapCount` (uint8_t) - Number of mipmap levels. A value of `1` means no mipmaps (only the base level is stored). Larger values allow for mipmapped sampling. - `m_UsageHintBits` (uint8_t) - Bitfield of usage hints. Indicates how the texture will be used (e.g. sampling, render target, storage image). See dmGraphics::TextureUsageFlag ### TextureFilter *Type:* ENUM Texture filtering modes. Controls how texels are sampled when scaling or rotating textures **Members** - `TEXTURE_FILTER_DEFAULT` - Default texture filtering mode. Depeneds on graphics backend (for example, for OpenGL - TEXTURE_FILTER_LINEAR) - `TEXTURE_FILTER_NEAREST` - Nearest-neighbor sampling (blocky look, fastest) - `TEXTURE_FILTER_LINEAR` - Linear interpolation between texels (smooth look) - `TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST` - Nearest mipmap level, nearest texel - `TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR` - Linear blend between two mipmap levels, nearest texel - `TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST` - Nearest mipmap level, linear texel - `TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR` - Linear blend between mipmap levels and texels (trilinear) ### TextureFormat *Type:* ENUM Pixel formats supported by textures. Includes uncompressed, compressed, and floating-point variants **Members** - `TEXTURE_FORMAT_LUMINANCE` - Single-channel grayscale - `TEXTURE_FORMAT_LUMINANCE_ALPHA` - Two-channel grayscale + alpha - `TEXTURE_FORMAT_RGB` - Standard 24-bit RGB color - `TEXTURE_FORMAT_RGBA` - Standard 32-bit RGBA color - `TEXTURE_FORMAT_RGB_16BPP` - Packed 16-bit RGB (lower precision, saves memory) - `TEXTURE_FORMAT_RGBA_16BPP` - Packed 16-bit RGBA - `TEXTURE_FORMAT_DEPTH` - Depth buffer texture (used for depth testing) - `TEXTURE_FORMAT_STENCIL` - Stencil buffer texture - `TEXTURE_FORMAT_RGB_PVRTC_2BPPV1` - PVRTC compressed RGB at 2 bits per pixel - `TEXTURE_FORMAT_RGB_PVRTC_4BPPV1` - PVRTC compressed RGB at 4 bits per pixel - `TEXTURE_FORMAT_RGBA_PVRTC_2BPPV1` - PVRTC compressed RGBA at 2 bits per pixel - `TEXTURE_FORMAT_RGBA_PVRTC_4BPPV1` - PVRTC compressed RGBA at 4 bits per pixel - `TEXTURE_FORMAT_RGB_ETC1` - ETC1 compressed RGB (no alpha support) - `TEXTURE_FORMAT_R_ETC2` - ETC2 single-channel - `TEXTURE_FORMAT_RG_ETC2` - ETC2 two-channel - `TEXTURE_FORMAT_RGBA_ETC2` - ETC2 four-channel (with alpha) - `TEXTURE_FORMAT_RGBA_ASTC_4X4` - ASTC block-compressed 4×4 - `TEXTURE_FORMAT_RGB_BC1` - BC1/DXT1 compressed RGB - `TEXTURE_FORMAT_RGBA_BC3` - BC3/DXT5 compressed RGBA - `TEXTURE_FORMAT_R_BC4` - BC4 single-channel - `TEXTURE_FORMAT_RG_BC5` - BC5 two-channel - `TEXTURE_FORMAT_RGBA_BC7` - BC7 high-quality compressed RGBA - `TEXTURE_FORMAT_RGB16F` - Half-precision float RGB - `TEXTURE_FORMAT_RGB32F` - Full 32-bit float RGB - `TEXTURE_FORMAT_RGBA16F` - Half-precision float RGBA - `TEXTURE_FORMAT_RGBA32F` - Full 32-bit float RGBA - `TEXTURE_FORMAT_R16F` - Half-precision float single channel - `TEXTURE_FORMAT_RG16F` - Half-precision float two channels - `TEXTURE_FORMAT_R32F` - Full 32-bit float single channel - `TEXTURE_FORMAT_RG32F` - Full 32-bit float two channels - `TEXTURE_FORMAT_RGBA32UI` - Internal: 32-bit unsigned integer RGBA (not script-exposed) - `TEXTURE_FORMAT_BGRA8U` - Internal: 32-bit BGRA layout - `TEXTURE_FORMAT_R32UI` - Internal: 32-bit unsigned integer single channel - `TEXTURE_FORMAT_RGBA_ASTC_5X4` - ASTC 5x4 block compression - `TEXTURE_FORMAT_RGBA_ASTC_5X5` - ASTC 5x5 block compression - `TEXTURE_FORMAT_RGBA_ASTC_6X5` - ASTC 6x5 block compression - `TEXTURE_FORMAT_RGBA_ASTC_6X6` - ASTC 6x6 block compression - `TEXTURE_FORMAT_RGBA_ASTC_8X5` - ASTC 8x5 block compression - `TEXTURE_FORMAT_RGBA_ASTC_8X6` - ASTC 8x6 block compression - `TEXTURE_FORMAT_RGBA_ASTC_8X8` - ASTC 8x8 block compression - `TEXTURE_FORMAT_RGBA_ASTC_10X5` - ASTC 10x5 block compression - `TEXTURE_FORMAT_RGBA_ASTC_10X6` - ASTC 10x6 block compression - `TEXTURE_FORMAT_RGBA_ASTC_10X8` - ASTC 10x8 block compression - `TEXTURE_FORMAT_RGBA_ASTC_10X10` - ASTC 10x10 block compression - `TEXTURE_FORMAT_RGBA_ASTC_12X10` - ASTC 12x10 block compression - `TEXTURE_FORMAT_RGBA_ASTC_12X12` - ASTC 12x12 block compression ### TextureParams *Type:* STRUCT Texture update parameters. Defines a block of pixel data to be uploaded to a texture, along with filtering, wrapping, and sub-region update options. Typically used when calling texture upload/update functions after a texture object has been created with TextureCreationParams **Members** - `m_Data` (const void*) - Pointer to raw pixel data in CPU memory. The format is defined by `m_Format` - `m_DataSize` (uint32_t) - Size of the pixel data in bytes. Must match the expected size from width, height, depth, and format - `m_Format` (dmGraphics::TextureFormat) - Format of the pixel data (e.g. RGBA, RGB, compressed formats). Dictates how the GPU interprets the memory pointed by `m_Data` - `m_MinFilter` (dmGraphics::TextureFilter) - Minification filter (applied when shrinking). Determines how pixels are sampled when the texture is displayed smaller than its native resolution - `m_MagFilter` (dmGraphics::TextureFilter) - Magnification filter (applied when enlarging). Determines how pixels are sampled when the texture is displayed larger than its native resolution - `m_UWrap` (dmGraphics::TextureWrap) - Wrapping mode for U (X) texture coordinate. Controls behavior when texture coordinates exceed [0,1] - `m_VWrap` (dmGraphics::TextureWrap) - Wrapping mode for V (Y) texture coordinate. Controls behavior when texture coordinates exceed [0,1] - `m_X` (uint32_t) - X offset in pixels for sub-texture updates. Defines the left edge of the destination region - `m_Y` (uint32_t) - Y offset in pixels for sub-texture updates. Defines the top edge of the destination region - `m_Z` (uint32_t) - Z offset (depth layer) for 3D textures. Ignored for standard 2D textures - `m_Slice` (uint32_t) - Slice index in an array texture where the data should be uploaded - `m_Width` (uint16_t) - Width of the pixel data block in pixels. Used for both full uploads and sub-updates - `m_Height` (uint16_t) - Height of the pixel data block in pixels. Used for both full uploads and sub-updates - `m_Depth` (uint16_t) - Depth of the pixel data block in pixels. Only relevant for 3D textures - `m_LayerCount` (uint8_t) - Number of layers to update. For array textures, this specifies how many pages are updated - `m_MipMap` (uint8_t) - Only 7 bit available Mipmap level to update. Level 0 is the base level, higher levels are progressively downscaled versions - `m_SubUpdate` (uint8_t) - If true, this represents a partial texture update (sub-region), using `m_X`, `m_Y`, `m_Z`, and `m_Slice` offsets. If false, the entire texture/mipmap level is replaced ### TextureStatusFlags *Type:* ENUM Texture data upload status flags **Members** - `TEXTURE_STATUS_OK` - Texture updated and ready-to-use - `TEXTURE_STATUS_DATA_PENDING` - Data upload to the texture is in progress ### TextureType *Type:* ENUM Texture types **Members** - `TEXTURE_TYPE_2D` - `TEXTURE_TYPE_2D_ARRAY` - `TEXTURE_TYPE_3D` - `TEXTURE_TYPE_CUBE_MAP` - `TEXTURE_TYPE_IMAGE_2D` - `TEXTURE_TYPE_IMAGE_3D` - `TEXTURE_TYPE_SAMPLER` - `TEXTURE_TYPE_TEXTURE_2D` - `TEXTURE_TYPE_TEXTURE_2D_ARRAY` - `TEXTURE_TYPE_TEXTURE_3D` - `TEXTURE_TYPE_TEXTURE_CUBE` ### TextureWrap *Type:* ENUM Texture addressing/wrapping modes. Controls behavior when texture coordinates fall outside the [0,1] range **Members** - `TEXTURE_WRAP_CLAMP_TO_BORDER` - Clamp to the color defined as 'border' - `TEXTURE_WRAP_CLAMP_TO_EDGE` - Clamp to the edge pixel of the texture - `TEXTURE_WRAP_MIRRORED_REPEAT` - Repeat texture, mirroring every other repetition - `TEXTURE_WRAP_REPEAT` - Repeat texture in a tiled fashion ### Type *Type:* ENUM Data type. Represents scalar, vector, matrix, image, or sampler types used for vertex attributes, uniforms, and shader interface definitions **Members** - `TYPE_BYTE` - Signed 8-bit integer. Compact storage, often used for colors, normals, or compressed vertex attributes - `TYPE_UNSIGNED_BYTE` - Unsigned 8-bit integer. Common for color channels (0–255) or normalized texture data - `TYPE_SHORT` - Signed 16-bit integer. Used for medium-range numeric attributes such as bone weights or coordinates with normalization - `TYPE_UNSIGNED_SHORT` - Unsigned 16-bit integer. Often used for indices or normalized attributes when extra precision over bytes is required - `TYPE_INT` - Signed 32-bit integer. Typically used for uniform values, shader constants, or counters - `TYPE_UNSIGNED_INT` - Unsigned 32-bit integer. Used for indices, IDs, or GPU counters - `TYPE_FLOAT` - 32-bit floating point. Standard for most vertex attributes and uniform values (positions, UVs, weights) - `TYPE_FLOAT_VEC4` - 4-component floating-point vector (`vec4` in GLSL). Typically used for homogeneous coordinates, colors (RGBA), or combined attributes - `TYPE_FLOAT_MAT4` - 4x4 floating-point matrix (`mat4` in GLSL). Standard for 3D transformations (model, view, projection) - `TYPE_SAMPLER_2D` - 2D texture sampler. Standard type for most texture lookups - `TYPE_SAMPLER_CUBE` - Cube map sampler. Used for environment mapping, reflections, and skyboxes - `TYPE_SAMPLER_2D_ARRAY` - Array of 2D texture samplers. Enables efficient texture indexing when using multiple layers (e.g. terrain textures, sprite atlases) - `TYPE_FLOAT_VEC2` - 2-component floating-point vector (`vec2` in GLSL). Commonly used for texture coordinates or 2D positions - `TYPE_FLOAT_VEC3` - 3-component floating-point vector (`vec3` in GLSL). Used for positions, normals, and directions in 3D space - `TYPE_FLOAT_MAT2` - 2x2 floating-point matrix (`mat2` in GLSL). Used in transformations (e.g. 2D rotations, scaling) - `TYPE_FLOAT_MAT3` - 3x3 floating-point matrix (`mat3` in GLSL). Commonly used for normal matrix calculations in lighting - `TYPE_IMAGE_2D` - 2D image object. Unlike samplers, images allow read/write access in shaders (e.g. compute shaders or image load/store operations) - `TYPE_TEXTURE_2D` - 2D texture object handle. Represents an actual GPU texture resource - `TYPE_SAMPLER` - Generic sampler handle, used as a placeholder for texture units without specifying the dimension - `TYPE_TEXTURE_2D_ARRAY` - 2D texture array object handle - `TYPE_TEXTURE_CUBE` - Cube map texture object handle - `TYPE_SAMPLER_3D` - 3D texture sampler. Used for volumetric effects, noise fields, or voxel data - `TYPE_TEXTURE_3D` - 3D texture object handle - `TYPE_IMAGE_3D` - 3D image object. Used for compute-based volume processing - `TYPE_SAMPLER_3D_ARRAY` - Array of 3D texture samplers - `TYPE_TEXTURE_3D_ARRAY` - 3D texture array object handle # Graphics {#apis:engine-graphics-src-dmsdk-graphics-graphics_native-h} **Namespace:** `dmGraphics` **Language:** C++ **Type:** Defold C++ **File:** `graphics_native.h` **Source:** `engine/graphics/src/dmsdk/graphics/graphics_native.h` **Include:** `dmsdk/graphics/graphics_native.h` Platform specific native graphics functions. ## API ### dmGraphics::GetNativeAndroidActivity *Type:* FUNCTION Get Android native jobject. Any other platform return zero. **Returns** - `jobject` (jobject) - native handle ### dmGraphics::GetNativeAndroidApp *Type:* FUNCTION Get Android app object. Any other platform return zero. **Returns** - `app` (struct android_app*) - native handle ### dmGraphics::GetNativeAndroidEGLContext *Type:* FUNCTION Get Android EGLContext native handle (EGLContext). Any other platform return zero. **Returns** - `EGLContext` (EGLContext) - native handle ### dmGraphics::GetNativeAndroidEGLSurface *Type:* FUNCTION Get Android EGLSurface native handle (EGLSurface). Any other platform return zero. **Returns** - `EGLSurface` (EGLSurface) - native handle ### dmGraphics::GetNativeAndroidJavaVM *Type:* FUNCTION Get Android JavaVM ptr. Any other platform return zero. **Returns** - `JavaVM*` (JavaVM*) - native handle ### dmGraphics::GetNativeiOSEAGLContext *Type:* FUNCTION Get iOS EAGLContext native handle (id). Any other platform return zero. **Returns** - `id` (id) - native handle ### dmGraphics::GetNativeiOSUIView *Type:* FUNCTION Get iOS UIView native handle (id). Any other platform return zero. **Returns** - `id` (id) - native handle ### dmGraphics::GetNativeiOSUIWindow *Type:* FUNCTION Get iOS UIWindow native handle (id). Any other platform return zero. **Returns** - `id` (id) - native handle ### dmGraphics::GetNativeOSXNSOpenGLContext *Type:* FUNCTION Get OSX NSOpenGLContext native handle (id). Any other platform return zero. **Returns** - `id` (id) - native handle ### dmGraphics::GetNativeOSXNSView *Type:* FUNCTION Get OSX NSView native handle (id). Any other platform return zero. **Returns** - `id` (id) - native handle ### dmGraphics::GetNativeOSXNSWindow *Type:* FUNCTION Get OSX NSWindow native handle (id). Any other platform return zero. **Returns** - `id` (id) - native handle ### dmGraphics::GetNativeWindowsHGLRC *Type:* FUNCTION Get Win32 gl rendercontext native handle (HGLRC). Any other platform return zero. **Returns** - `HGLRC` (HGLRC) - native handle ### dmGraphics::GetNativeWindowsHWND *Type:* FUNCTION Get Win32 windows native handle (HWND). Any other platform return zero. **Returns** - `HWND` (HWND) - native handle ### dmGraphics::GetNativeX11GLXContext *Type:* FUNCTION Get Linux X11GLXContext native handle (GLXContext). Any other platform return zero. **Returns** - `GLXContext` (GLXContext) - native handle ### dmGraphics::GetNativeX11Window *Type:* FUNCTION Get Linux X11Window windows native handle (Window). Any other platform return zero. **Returns** - `Window` (Window) - native handle # Graphics OpenGL {#apis:engine-graphics-src-dmsdk-graphics-graphics_opengl-h} **Namespace:** `dmGraphics` **Language:** C++ **Type:** Defold C++ **File:** `graphics_opengl.h` **Source:** `engine/graphics/src/dmsdk/graphics/graphics_opengl.h` **Include:** `dmsdk/graphics/graphics_opengl.h` Graphics OpenGL API ## API ### OpenGLGetDefaultFramebufferId *Type:* FUNCTION Get the default framebuffer ID **Parameters** - `context` (dmGraphics::HContext) - the OpenGL context **Returns** - `framebuffer` (uint32_t) - the framebuffer id ### OpenGLGetRenderTargetId *Type:* FUNCTION Get the OpenGL render target id from a render target **Parameters** - `context` (dmGraphics::HContext) - the OpenGL context - `render_target` (dmGraphics::HRenderTarget) - the render target to get the ID from **Returns** - `id` (uint32_t) - the OpenGL render target id # Graphics Vulkan {#apis:engine-graphics-src-dmsdk-graphics-graphics_vulkan-h} **Namespace:** `dmGraphics` **Language:** C++ **Type:** Defold C++ **File:** `graphics_vulkan.h` **Source:** `engine/graphics/src/dmsdk/graphics/graphics_vulkan.h` **Include:** `dmsdk/graphics/graphics_vulkan.h` Graphics Vulkan API ## API ### VkDescriptorPool *Type:* TYPEDEF ### VkDevice *Type:* TYPEDEF ### VulkanCreateDescriptorPool *Type:* FUNCTION Create Vulkan descriptor pool. No need to deallocate descripto pool manualy because it will be deallocated automatically when context will be destroyed. Only available when using Mac/iOS. **Parameters** - `vk_device` (VkDevice) - the Vulkan device handle - `max_descriptors` (uint16_t) - maximum size of allocated pool - `vk_descriptor_pool_out` (VkDescriptorPool*) - result Vulkan descriptor pool **Returns** - `result` (bool) - true if creation was successful. Otherwise returns false ### VulkanGetActiveSwapChainTexture *Type:* FUNCTION Get the current swap chain texture **Parameters** - `context` (dmGraphics::HContext) - the Vulkan context **Returns** - `swapchain` (dmGraphics::HTexture) - the swap chain texture for the current frame ### VulkanGetCurrentFrameCommandBuffer *Type:* FUNCTION Get Vulkan command buffer which used at the current frame. Only available when using Mac/iOS. **Parameters** - `context` (dmGraphics::HContext) - the Vulkan context **Returns** - `command_buffer` (VkCommandBuffer) - the Vulkan command buffer ### VulkanGetDevice *Type:* FUNCTION Get Vulkan device handle. Only available when using Mac/iOS. **Parameters** - `context` (dmGraphics::HContext) - the Vulkan context **Returns** - `device` (VkDevice) - the Vulkan device handle ### VulkanGetGraphicsQueue *Type:* FUNCTION Get Vulkan graphics queue handle. Only available when using Mac/iOS. **Parameters** - `context` (dmGraphics::HContext) - the Vulkan context **Returns** - `queue` (VkQueue) - the Vulkan graphics queue ### VulkanGetGraphicsQueueFamily *Type:* FUNCTION Get Vulkan queue family. Only available when using Mac/iOS. **Parameters** - `context` (dmGraphics::HContext) - the Vulkan context return family uint16_t graphics queue family ### VulkanGetImage *Type:* FUNCTION Get the native Vulkan image handle from an engine texture handle. Returns 0 if the texture handle does not resolve to a Vulkan image. **Parameters** - `context` (dmGraphics::HContext) - the Vulkan context - `texture` (dmGraphics::HTexture) - the texture handle **Returns** - `image` (VkImage) - the Vulkan image handle ### VulkanGetImageView *Type:* FUNCTION Get the native Vulkan image view handle from an engine texture handle. Returns 0 if the texture handle does not resolve to a Vulkan image view. **Parameters** - `context` (dmGraphics::HContext) - the Vulkan context - `texture` (dmGraphics::HTexture) - the texture handle **Returns** - `image_view` (VkImageView) - the Vulkan image view handle ### VulkanGetInstance *Type:* FUNCTION Get Vulkan instance handle. Only available when using Mac/iOS. **Parameters** - `context` (dmGraphics::HContext) - the Vulkan context **Returns** - `instance` (VkInstance) - the Vulkan instance handle ### VulkanGetPhysicalDevice *Type:* FUNCTION Get Vulkan physical device handle. Only available when using Mac/iOS. **Parameters** - `context` (dmGraphics::HContext) - the Vulkan context **Returns** - `physical_device` (VkPhysicalDevice) - the Vulkan physical device handle ### VulkanGetRenderPass *Type:* FUNCTION Get Vulkan render pass handle. Only available when using Mac/iOS. **Parameters** - `context` (dmGraphics::HContext) - the Vulkan context **Returns** - `render_pass` (VkRenderPass) - the Vulkan render pass handle ### VulkanGraphicsCommandQueueToMetal *Type:* FUNCTION Get the native MTLCommandQueue from the Vulkan context. Only available when using Mac/iOS. **Parameters** - `context` (dmGraphics::HContext) - the Vulkan context **Returns** - `mtl_queue` (id) - the Metal graphics queue wrapped with a (__bridge void*) ### VulkanTextureToMetal *Type:* FUNCTION Get a native MTLTexture from a Vulkan HTexture. Only available when using Mac/iOS. **Parameters** - `context` (dmGraphics::HContext) - the Vulkan context - `texture` (dmGraphics::HTexture) - the texture **Returns** - `mtl_texture` (id) - the Metal texture wrapped with a (__bridge void*) # Gui {#apis:engine-gui-src-dmsdk-gui-gui-h} **Namespace:** `dmGui` **Language:** C++ **Type:** Defold C++ **File:** `gui.h` **Source:** `engine/gui/src/dmsdk/gui/gui.h` **Include:** `dmsdk/gui/gui.h` Defold GUI system ## API ### AdjustMode *Type:* ENUM **Members** - `ADJUST_MODE_FIT` - //!< 0 - `ADJUST_MODE_ZOOM` - //!< 1 - `ADJUST_MODE_STRETCH` - //!< 2 ### AdjustReference *Type:* ENUM **Members** - `ADJUST_REFERENCE_PARENT` - `ADJUST_REFERENCE_DISABLED` ### DeleteNode *Type:* FUNCTION Defer delete a node **Parameters** - `scene` (dmGui::HScene) - the gui scene - `node` (dmGui::HNode) - the node to delete ### GetFirstChildNode *Type:* FUNCTION Get first child node **Parameters** - `scene` (dmGui::HScene) - the gui scene - `node` (dmGui::HNode) - Gets the first child node. If 0, gets the first top level node. **Returns** - `child` (dmGui::HNode) - The first child node ### GetNextNode *Type:* FUNCTION Get next sibling **Parameters** - `scene` (dmGui::HScene) - the gui scene - `node` (dmGui::HNode) - the current sibling **Returns** - `sibling` (dmGui::HNode) - the next sibling, or INVALID_HANDLE if no more siblings ### GetNodeCustomData *Type:* FUNCTION get node custom type **Parameters** - `scene` (dmGui::HScene) - the gui scene - `node` (HNode) - the gui node **Returns** - `type` (uint32_t) - the custom type. Or 0 if it is no custom type ### GetNodeCustomData *Type:* FUNCTION get node custom data **Parameters** - `scene` (dmGui::HScene) - the gui scene - `node` (HNode) - the gui node **Returns** - `data` (void*) - the custom data created per node by the gui node type extension ### GetNodeId *Type:* FUNCTION Get the id of a node. **Parameters** - `scene` (dmGui::HScene) - the gui scene - `node` (dmGui::HNode) - the gui node **Returns** - `id` (dmhash_t) - the id of the node ### GetNodeIsBone *Type:* FUNCTION Query if the node is a bone **Parameters** - `scene` (dmGui::HScene) - the gui scene - `node` (dmGui::HNode) - the gui node **Returns** - `result` (bool) - true if the node is a bone ### GetNodeParent *Type:* FUNCTION Get the parent of a gui node **Parameters** - `scene` (dmGui::HScene) - the gui scene - `node` (dmGui::HNode) - the gui node **Returns** - `parent` (dmGui::HNode) - the parent, or INVALID_HANDLE is unsuccessful ### GetNodeProperty *Type:* FUNCTION Get property value **Parameters** - `scene` (dmGui::HScene) - scene - `node` (dmGui::HNode) - node - `property` (dmGui::Property) - property enum **Returns** - `value` (dmVMath::Vector4) ### GetNodeTextureId *Type:* FUNCTION get node texture **Parameters** - `scene` (dmGui::HScene) - the gui scene - `node` (HNode) - the gui node **Returns** - `texture` (dmhash_t) - the currently assigned texture ### GetResource *Type:* FUNCTION Gets a resource by its resource alias. **Parameters** - `scene` (dmGui::HScene) - the gui scene - `resource_id` (dmhash_t) - the resource alias - `suffix_with_dot` (dmhash_t) - the hash of the suffix: hash(".spinescenec") **Returns** - `resource` (void*) - the resource if successful ### HContext *Type:* TYPEDEF A handle to a gui context ### HNode *Type:* TYPEDEF A handle to a gui node ### HScene *Type:* TYPEDEF A handle to a gui scene ### HScript *Type:* TYPEDEF A handle to a gui script ### HTextureSource *Type:* TYPEDEF A handle to a texture source, which can be a pointer to a resource, a dmGraphics::HTexture or a dynamic texture created from a gui script. ### INVALID_HANDLE *Type:* FUNCTION Invalid node handle ### LuaPushNode *Type:* FUNCTION Pushes a dmGui::HNode to the stack **Parameters** - `L` (lua_State*) - the Lua scene - `scene` (dmGui::HScene) - the gui scene - `node` (HNode) - the gui node ### NewNode *Type:* FUNCTION **Parameters** - `scene` (dmGui::HScene) - the gui scene - `position` (dmVMath::Point3) - the position - `size` (dmVMath::Vector3) - the size - `node_type` (dmGui::NodeType) - the node type - `custom_type` (uint32_t) - If node_type == dmGui::NODE_TYPE_CUSTOM, then this is used to create a custom node data for the registered custom type **Returns** - `node` (dmGui::HNode) - the created node ### NodeTextureType *Type:* ENUM This enum denotes what kind of texture type the m_Texture pointer is referencing. **Members** - `NODE_TEXTURE_TYPE_NONE` - `NODE_TEXTURE_TYPE_TEXTURE` - `NODE_TEXTURE_TYPE_TEXTURE_SET` ### Playback *Type:* ENUM **Members** - `PLAYBACK_ONCE_FORWARD` - `PLAYBACK_ONCE_BACKWARD` - `PLAYBACK_ONCE_PINGPONG` - `PLAYBACK_LOOP_FORWARD` - `PLAYBACK_LOOP_BACKWARD` - `PLAYBACK_LOOP_PINGPONG` - `PLAYBACK_NONE` ### Property *Type:* ENUM **Members** - `PROPERTY_POSITION` - //!< 0 - `PROPERTY_ROTATION` - //!< 1 - `PROPERTY_SCALE` - //!< 2 - `PROPERTY_COLOR` - //!< 3 - `PROPERTY_SIZE` - //!< 4 - `PROPERTY_OUTLINE` - //!< 5 - `PROPERTY_SHADOW` - //!< 6 - `PROPERTY_SLICE9` - //!< 7 - `PROPERTY_PIE_PARAMS` - //!< 8 - `PROPERTY_TEXT_PARAMS` - //!< 9 - `PROPERTY_COUNT` - //!< 10 ### Result *Type:* ENUM **Members** - `NODE_TYPE_BOX` - //!< 0, - `NODE_TYPE_TEXT` - //!< 1, - `NODE_TYPE_PIE` - //!< 2, - `NODE_TYPE_TEMPLATE` - //!< 3, - `NODE_TYPE_PARTICLEFX` - //!< 5, - `NODE_TYPE_CUSTOM` - //!< 6, - `NODE_TYPE_COUNT` - //!< 7, ### Result *Type:* ENUM **Members** - `RESULT_OK` - //!< 0 - `RESULT_SYNTAX_ERROR` - //!< -1 - `RESULT_SCRIPT_ERROR` - //!< -2 - `RESULT_OUT_OF_RESOURCES` - //!< -4 - `RESULT_RESOURCE_NOT_FOUND` - //!< -5 - `RESULT_TEXTURE_ALREADY_EXISTS` - //!< -6 - `RESULT_INVAL_ERROR` - //!< -7 - `RESULT_INF_RECURSION` - //!< -8 - `RESULT_DATA_ERROR` - //!< -9 - `RESULT_WRONG_TYPE` - //!< -10 ### SetNodeAdjustMode *Type:* FUNCTION Set adjust mode **Parameters** - `scene` (dmGui::HScene) - scene - `node` (dmGui::HNode) - node - `adjust_mode` (AdjustMode) - the adjust mode ### SetNodeId *Type:* FUNCTION Set the id of a node. **Notes** - The id must be unique **Parameters** - `scene` (dmGui::HScene) - the gui scene - `node` (dmGui::HNode) - the gui node - `id` (dmhash_t) - the id ### SetNodeIsBone *Type:* FUNCTION Set the bone state of the node **Parameters** - `scene` (dmGui::HScene) - the gui scene - `node` (dmGui::HNode) - the gui node - `is_bone` (bool) - true if the node is ot be used as a bone ### SetNodeParent *Type:* FUNCTION Set the parent of a gui node **Parameters** - `scene` (dmGui::HScene) - the gui scene - `node` (dmGui::HNode) - the gui node - `parent` (dmGui::HNode) - the new parent. May be null - `keep_scene_transform` (bool) - true to keep the world position **Returns** - `result` (dmGui::Result) - dmGui::RESULT_OK is successful ### SetNodeProperty *Type:* FUNCTION Set property value **Parameters** - `scene` (dmGui::HScene) - scene - `node` (dmGui::HNode) - node - `property` (dmGui::Property) - property enum - `value` (dmVMath::Vector4) ### SetNodeTexture *Type:* FUNCTION set node texture **Parameters** - `scene` (dmGui::HScene) - the gui scene - `node` (HNode) - the gui node - `texture_id` (dmhash_t) - the texture id ### SetNodeTexture *Type:* FUNCTION set node texture **Parameters** - `scene` (dmGui::HScene) - the gui scene - `node` (HNode) - the gui node - `type` (NodeTextureType) - the type of texture - `texture` (void*) - A pointer to a e.g. dmGameSystem::TextureSetResource* # Hid {#apis:engine-hid-src-dmsdk-hid-hid-h} **Namespace:** `dmHid` **Language:** C++ **Type:** Defold C++ **File:** `hid.h` **Source:** `engine/hid/src/dmsdk/hid/hid.h` **Include:** `dmsdk/hid/hid.h` Used to add input to the engine ## API ### AddKeyboardChar *Type:* FUNCTION Add text input **Parameters** - `keyboard` (dmHID::HContext) - context handle - `chr` (int) - The character (unicode) ### AddTouch *Type:* FUNCTION Adds a touch event touch. **Parameters** - `device` (dmHID::HTouchDevice) - device handle - `x` (int32_t) - x-coordinate of the position - `y` (int32_t) - y-coordinate of the position - `id` (uint32_t) - identifier of touch - `phase` (dmHID::Phase) - phase of touch ### dmHID::HContext *Type:* TYPEDEF HID context handle ### dmHID::HGamepad *Type:* TYPEDEF gamepad context handle ### dmHID::HKeyboard *Type:* TYPEDEF keyboard context handle ### dmHID::HMouse *Type:* TYPEDEF mouse context handle ### dmHID::HTouchDevice *Type:* TYPEDEF touch device context handle ### dmHID::INVALID_GAMEPAD_HANDLE [type: dmHID::HGamepad] *Type:* CONSTANT invalid gamepad handle ### dmHID::INVALID_KEYBOARD_HANDLE [type: dmHID::HKeyboard] *Type:* CONSTANT invalid keyboard handle ### dmHID::INVALID_MOUSE_HANDLE [type: dmHID::HMouse] *Type:* CONSTANT invalid mouse handle ### dmHID::INVALID_TOUCHDEVICE_HANDLE [type: dmHID::HTouchDevice] *Type:* CONSTANT invalid touch devicehandle ### dmHID::MAX_CHAR_COUNT *Type:* CONSTANT max number of characters ### dmHID::MAX_GAMEPAD_AXIS_COUNT [type: uint32_t] *Type:* CONSTANT Maximum number of gamepad axis supported ### dmHID::MAX_GAMEPAD_BUTTON_COUNT [type: uint32_t] *Type:* CONSTANT Maximum number of gamepad buttons supported ### dmHID::MAX_GAMEPAD_COUNT [type: uint32_t] *Type:* CONSTANT Maximum number of gamepads supported ### dmHID::MAX_GAMEPAD_HAT_COUNT [type: uint32_t] *Type:* CONSTANT Maximum number of gamepad hats supported ### dmHID::MAX_KEYBOARD_COUNT [type: uint32_t] *Type:* CONSTANT Maximum number of keyboards supported ### dmHID::MAX_MOUSE_COUNT [type: uint32_t] *Type:* CONSTANT Maximum number of mice supported ### dmHID::MAX_TOUCH_COUNT [type: uint32_t] *Type:* CONSTANT Maximum number of simultaneous touches supported ### dmHID::MAX_TOUCH_DEVICE_COUNT [type: uint32_t] *Type:* CONSTANT Maximum number of touch devices supported ### GamepadPacket *Type:* STRUCT Contains the current state of a gamepad **Notes** - implementation is internal, use the proper accessor functions ### GetGamePad *Type:* FUNCTION gets a gamepad device handle **Parameters** - `context` (dmHID::HContext) - context in which to find the gamepad - `index` (uint8_t) - device index **Returns** - `gamepad` (dmHID::HGamepad) - Handle to gamepad. dmHID::INVALID_GAMEPAD_HANDLE if not available ### GetGamePad *Type:* FUNCTION gets a gamepad device handle **Parameters** - `gamepad` (dmHID::HGamepad) - Handle to gamepad - `out` (void**) - Platform specific user id data **Returns** - `result` (boolean) - true if gamepad has a user id data assigned to it ### GetGamepadButton *Type:* FUNCTION Convenience function to retrieve the state of a gamepad button from a gamepad packet. **Parameters** - `packet` (dmHID::GamepadPacket) - Gamepad packet - `button` (uint32_t) - The requested button **Returns** - `success` (bool) - True if the button is currently pressed down. ### GetGamepadHat *Type:* FUNCTION Convenience function to retrieve the state of a gamepad hat from a gamepad packet. **Parameters** - `packet` (dmHID::GamepadPacket) - Gamepad packet - `hat` (uint32_t) - The requested hat index - `out_hat_value` (uint8_t) - Hat value out argument **Returns** - `success` (bool) - True if the hat has data. ### GetGamepadPacket *Type:* FUNCTION Obtain a gamepad packet reflecting the current input state of the gamepad in a HID context. **Parameters** - `gamepad` (dmHID::HGamepad) - gamepad handle - `out_packet` (dmHID::GamepadPacket) - Gamepad packet out argument **Returns** - `success` (bool) - True if the packet was successfully updated. ### GetKeyboard *Type:* FUNCTION gets a keyboard handle **Parameters** - `context` (dmHID::HContext) - context in which to find the gamepad - `index` (uint8_t) - device index **Returns** - `keyboard` (dmHID::HKeyboard) - Handle to keyboard. dmHID::INVALID_KEYBOARD_HANDLE if not available ### GetMouse *Type:* FUNCTION gets a mouse handle **Parameters** - `context` (dmHID::HContext) - context in which to find the gamepad - `index` (uint8_t) - device index **Returns** - `mouse` (dmHID::HMouse) - Handle to mouse. dmHID::INVALID_MOUSE_HANDLE if not available ### GetMouseButton *Type:* FUNCTION Convenience function to retrieve the state of a mouse button from a mouse packet. **Parameters** - `packet` (dmHID::MousePacket*) - Mouse packet - `button` (dmHID::MouseButton) - The requested button **Returns** - `result` (bool) - If the button was pressed or not ### GetMousePacket *Type:* FUNCTION Obtain a mouse packet reflecting the current input state of a HID context. **Parameters** - `mouse` (dmHID::HMouse) - context from which to retrieve the packet - `out_packet` (dmHID::MousePacket*) - Mouse packet out argument **Returns** - `result` (bool) - If the packet was successfully updated or not. ### GetTouchDevice *Type:* FUNCTION gets a touch device handle **Parameters** - `context` (dmHID::HContext) - context in which to find the gamepad - `index` (uint8_t) - device index **Returns** - `device` (dmHID::HTouchDevice) - Handle to touch device. dmHID::INVALID_TOUCH_DEVICE_HANDLE if not available ### Key *Type:* ENUM keyboard key enumeration **Members** - `dmHID::KEY_SPACE` - `dmHID::KEY_EXCLAIM` - `dmHID::KEY_QUOTEDBL` - `dmHID::KEY_HASH` - `dmHID::KEY_DOLLAR` - `dmHID::KEY_AMPERSAND` - `dmHID::KEY_QUOTE` - `dmHID::KEY_LPAREN` - `dmHID::KEY_RPAREN` - `dmHID::KEY_ASTERISK` - `dmHID::KEY_PLUS` - `dmHID::KEY_COMMA` - `dmHID::KEY_MINUS` - `dmHID::KEY_PERIOD` - `dmHID::KEY_SLASH` - `dmHID::KEY_0` - `dmHID::KEY_1` - `dmHID::KEY_2` - `dmHID::KEY_3` - `dmHID::KEY_4` - `dmHID::KEY_5` - `dmHID::KEY_6` - `dmHID::KEY_7` - `dmHID::KEY_8` - `dmHID::KEY_9` - `dmHID::KEY_COLON` - `dmHID::KEY_SEMICOLON` - `dmHID::KEY_LESS` - `dmHID::KEY_EQUALS` - `dmHID::KEY_GREATER` - `dmHID::KEY_QUESTION` - `dmHID::KEY_AT` - `dmHID::KEY_A` - `dmHID::KEY_B` - `dmHID::KEY_C` - `dmHID::KEY_D` - `dmHID::KEY_E` - `dmHID::KEY_F` - `dmHID::KEY_G` - `dmHID::KEY_H` - `dmHID::KEY_I` - `dmHID::KEY_J` - `dmHID::KEY_K` - `dmHID::KEY_L` - `dmHID::KEY_M` - `dmHID::KEY_N` - `dmHID::KEY_O` - `dmHID::KEY_P` - `dmHID::KEY_Q` - `dmHID::KEY_R` - `dmHID::KEY_S` - `dmHID::KEY_T` - `dmHID::KEY_U` - `dmHID::KEY_V` - `dmHID::KEY_W` - `dmHID::KEY_X` - `dmHID::KEY_Y` - `dmHID::KEY_Z` - `dmHID::KEY_LBRACKET` - `dmHID::KEY_BACKSLASH` - `dmHID::KEY_RBRACKET` - `dmHID::KEY_CARET` - `dmHID::KEY_UNDERSCORE` - `dmHID::KEY_BACKQUOTE` - `dmHID::KEY_LBRACE` - `dmHID::KEY_PIPE` - `dmHID::KEY_RBRACE` - `dmHID::KEY_TILDE` - `dmHID::KEY_ESC` - `dmHID::KEY_F1` - `dmHID::KEY_F2` - `dmHID::KEY_F3` - `dmHID::KEY_F4` - `dmHID::KEY_F5` - `dmHID::KEY_F6` - `dmHID::KEY_F7` - `dmHID::KEY_F8` - `dmHID::KEY_F9` - `dmHID::KEY_F10` - `dmHID::KEY_F11` - `dmHID::KEY_F12` - `dmHID::KEY_UP` - `dmHID::KEY_DOWN` - `dmHID::KEY_LEFT` - `dmHID::KEY_RIGHT` - `dmHID::KEY_LSHIFT` - `dmHID::KEY_RSHIFT` - `dmHID::KEY_LCTRL` - `dmHID::KEY_RCTRL` - `dmHID::KEY_LALT` - `dmHID::KEY_RALT` - `dmHID::KEY_TAB` - `dmHID::KEY_ENTER` - `dmHID::KEY_BACKSPACE` - `dmHID::KEY_INSERT` - `dmHID::KEY_DEL` - `dmHID::KEY_PAGEUP` - `dmHID::KEY_PAGEDOWN` - `dmHID::KEY_HOME` - `dmHID::KEY_END` - `dmHID::KEY_KP_0` - `dmHID::KEY_KP_1` - `dmHID::KEY_KP_2` - `dmHID::KEY_KP_3` - `dmHID::KEY_KP_4` - `dmHID::KEY_KP_5` - `dmHID::KEY_KP_6` - `dmHID::KEY_KP_7` - `dmHID::KEY_KP_8` - `dmHID::KEY_KP_9` - `dmHID::KEY_KP_DIVIDE` - `dmHID::KEY_KP_MULTIPLY` - `dmHID::KEY_KP_SUBTRACT` - `dmHID::KEY_KP_ADD` - `dmHID::KEY_KP_DECIMAL` - `dmHID::KEY_KP_EQUAL` - `dmHID::KEY_KP_ENTER` - `dmHID::KEY_KP_NUM_LOCK` - `dmHID::KEY_CAPS_LOCK` - `dmHID::KEY_SCROLL_LOCK` - `dmHID::KEY_PAUSE` - `dmHID::KEY_LSUPER` - `dmHID::KEY_RSUPER` - `dmHID::KEY_MENU` - `dmHID::KEY_BACK` - `dmHID::MAX_KEY_COUNT` ### KeyboardPacket *Type:* STRUCT Contains the current state of a keyboard **Notes** - implementation is internal, use the proper accessor functions ### MouseButton *Type:* ENUM mouse button enumeration **Members** - `dmHID::MOUSE_BUTTON_LEFT` - `dmHID::MOUSE_BUTTON_MIDDLE` - `dmHID::MOUSE_BUTTON_RIGHT` - `dmHID::MOUSE_BUTTON_1` - `dmHID::MOUSE_BUTTON_2` - `dmHID::MOUSE_BUTTON_3` - `dmHID::MOUSE_BUTTON_4` - `dmHID::MOUSE_BUTTON_5` - `dmHID::MOUSE_BUTTON_6` - `dmHID::MOUSE_BUTTON_7` - `dmHID::MOUSE_BUTTON_8` - `dmHID::MAX_MOUSE_BUTTON_COUNT` ### MousePacket *Type:* STRUCT Contains the current state of a mouse **Notes** - implementation is internal, use the proper accessor functions ### Phase *Type:* ENUM touch phase enumeration **Notes** - By convention the enumeration corresponds to the iOS values **Members** - `dmHID::PHASE_BEGAN` - `dmHID::PHASE_MOVED` - `dmHID::PHASE_STATIONARY` - `dmHID::PHASE_ENDED` - `dmHID::PHASE_CANCELLED` ### SetGamepadAxis *Type:* FUNCTION Sets the state of a gamepad axis. **Parameters** - `gamepad` (dmHID::HGamepad) - device handle - `axis` (uint32_t) - The requested axis [0, dmHID::MAX_GAMEPAD_AXIS_COUNT) - `value` (float) - axis value [-1, 1] ### SetGamepadButton *Type:* FUNCTION Sets the state of a gamepad button. **Parameters** - `gamepad` (dmHID::HGamepad) - device handle - `button` (uint32_t) - The requested button [0, dmHID::MAX_GAMEPAD_BUTTON_COUNT) - `value` (bool) - Button state ### SetKey *Type:* FUNCTION Sets the state of a key. **Parameters** - `keyboard` (dmHID::HKeyboard) - context handle - `key` (dmHID::Key) - The requested key - `value` (bool) - Key state ### SetMouseButton *Type:* FUNCTION Sets the state of a mouse button. **Parameters** - `mouse` (dmHID::HMouse) - device handle - `button` (dmHID::MouseButton) - The requested button - `value` (bool) - Button state ### SetMousePosition *Type:* FUNCTION Sets the position of a mouse. **Parameters** - `mouse` (dmHID::HMouse) - device handle - `x` (int32_t) - x-coordinate of the position - `y` (int32_t) - y-coordinate of the position ### SetMouseWheel *Type:* FUNCTION Sets the mouse wheel. **Parameters** - `mouse` (dmHID::HMouse) - device handle - `value` (int32_t) - wheel value ### Touch *Type:* STRUCT Data for a single touch, e.g. finger **Members** - `m_TapCount` (int32_t) - Single-click, double, etc - `m_Phase` (Phase) - Begin, end, etc - `m_X` (int32_t) - Current x - `m_Y` (int32_t) - Current y - `m_ScreenX` (int32_t) - Current x, in screen space - `m_ScreenY` (int32_t) - Current y, in screen space - `m_DX` (int32_t) - Current dx - `m_DY` (int32_t) - Current dy - `m_ScreenDX` (int32_t) - Current dx, in screen space - `m_ScreenDY` (int32_t) - Current dy, in screen space - `m_Id` (int32_t) - Touch id # Physics {#apis:engine-physics-src-dmsdk-physics-physics-h} **Namespace:** `dmPhysics` **Language:** C++ **Type:** Defold C++ **File:** `physics.h` **Source:** `engine/physics/src/dmsdk/physics/physics.h` **Include:** `dmsdk/physics/physics.h` Physics related structs and functions ## API ### HCollisionShape2D *Type:* TYPEDEF 2D collision shape handle ### HHullSet2D *Type:* TYPEDEF 2D Hull set handle # Render {#apis:engine-render-src-dmsdk-render-render-h} **Namespace:** `dmRender` **Language:** C++ **Type:** Defold C++ **File:** `render.h` **Source:** `engine/render/src/dmsdk/render/render.h` **Include:** `dmsdk/render/render.h` Api for render specific data ## API ### AddToRender *Type:* FUNCTION Adds a render object to the current render frame **Parameters** - `context` (dmRender::HRenderContext) - the context - `ro` (dmRender::RenderObject*) - the render object **Returns** - `result` (dmRender::Result) - the result ### ApplyMaterialConstants *Type:* FUNCTION **Parameters** - `render_context` (dmRender::HRenderContext) - Render context - `material` (dmRender::Material) - `render_object` (const dmRender::RenderObject*) ### ApplyMaterialSampler *Type:* FUNCTION **Parameters** - `render_context` (dmRender::HRenderContext) - `material` (dmRender::HMaterial) - `sampler` (dmRender::HSampler) - `value_index` (uint8_t) - `texture` (dmGraphics::HTexture) ### ClearMaterialTags *Type:* FUNCTION **Parameters** - `material` (dmRender::HMaterial) ### ClearNamedConstantBuffer *Type:* FUNCTION Clears a named constant buffer from any constants. **Parameters** - `buffer` (dmRender::HNamedConstantBuffer) - the constants buffer ### DeleteConstant *Type:* FUNCTION Deletes a shader program constant **Parameters** - `constant` (dmRender::HConstant) - The shader constant ### DeleteMaterial *Type:* FUNCTION **Parameters** - `render_context` (dmRender::HRenderContext) - Render context - `material` (dmRender::Material) ### DeleteNamedConstantBuffer *Type:* FUNCTION Deletes a named constant buffer **Parameters** - `buffer` (dmRender::HNamedConstantBuffer) - the constants buffer ### dmRender::GetMaterialVertexSpace *Type:* FUNCTION Get the vertex space (local or world) **Parameters** - `material` (dmRender::HMaterial) - the material **Returns** - `vertex_space` (dmRenderDDF::MaterialDesc::VertexSpace) - the vertex space ### dmRender::RenderObject::MAX_TEXTURE_COUNT *Type:* CONSTANT The maximum number of textures the render object can hold (16) ### FrustumOptions *Type:* STRUCT Frustum options used when setting up a draw call **Members** - `m_FrustumMatrix` (matrix4) - the frustum matrix - `m_SkipNearFarPlanes` (bool) - should the frustum culling use the near and far planes ### FrustumPlanes *Type:* ENUM Frustum planes to use in a frustum **Members** - `FRUSTUM_PLANES_SIDES` - `FRUSTUM_PLANES_ALL` ### GetConstantLocation *Type:* FUNCTION Gets the shader program constant location **Parameters** - `constant` (dmRender::HConstant) - The shader constant **Returns** - `location` (int32_t) - the location ### GetConstantName *Type:* FUNCTION Gets the shader program constant name **Parameters** - `constant` (dmRender::HConstant) - The shader constant **Returns** - `name` (dmhash_t) - the hash name ### GetConstantName *Type:* FUNCTION Gets the shader program constant name **Parameters** - `constant` (dmRender::HConstant) - The shader constant - `name` (dmhash_t) - the hash name ### GetConstantType *Type:* FUNCTION Gets the type of the constant **Parameters** - `constant` (dmRender::HConstant) - The shader constant **Returns** - `type` (dmRenderDDF::MaterialDesc::ConstantType) - the type of the constant ### GetConstantValues *Type:* FUNCTION Gets the shader program constant values **Parameters** - `constant` (dmRender::HConstant) - The shader constant - `num_values` (uint32_t*) - (out) the array num_values **Returns** - `values` (dmVMath::Vector4*) - the uniform values ### GetMaterialSampler *Type:* FUNCTION ### GetMaterialSamplerNameHash *Type:* FUNCTION **Parameters** - `material` (dmRender::HMaterial) - `unit` (uint32_t) **Returns** - `name_hash` (dmhash_t) ### GetMaterialSamplerUnit *Type:* FUNCTION **Parameters** - `material` (dmRender::HMaterial) - `name_hash` (dmhash_t) **Returns** - `sampler_unit` (uint32_t) ### GetMaterialTagListKey *Type:* FUNCTION Gets the key to the material tag list **Parameters** - `material` (dmGraphics::HMaterial) - the material **Returns** - `listkey` (uint32_t) - the list key ### GetNamedConstant *Type:* FUNCTION Gets a named constant from the buffer **Notes** - This give access to the internal memory of the constant **Parameters** - `buffer` (dmRender::HNamedConstantBuffer) - the constants buffer - `name_hash` (dmhash_t) - the name of the constant - `values` (dmVMath::Vector4**) - (out) the values. May not be null. - `num_values` (uint32_t*) - (out) the number of values. May not be null. **Returns** - `ok` (bool) - true if constant existed. ### GetNamedConstant *Type:* FUNCTION Gets a named constant from the buffer - with type information **Notes** - This give access to the internal memory of the constant **Parameters** - `buffer` (dmRender::HNamedConstantBuffer) - the constants buffer - `name_hash` (dmhash_t) - the name of the constant - `values` (dmVMath::Vector4**) - (out) the values. May not be null. - `num_values` (uint32_t*) - (out) the number of values. May not be null. - `constant_type` (dmRenderDDF::MaterialDesc::ConstantType*) - (out) the constant type. **Returns** - `ok` (bool) - true if constant existed. ### GetNamedConstantCount *Type:* FUNCTION Gets number of constants in the buffer **Parameters** - `buffer` (dmRender::HNamedConstantBuffer) - the constants buffer **Returns** - `ok` (bool) - true if constant existed. ### GetViewMatrix *Type:* FUNCTION **Parameters** - `render_context` (dmRender::HRenderContext) - Render context **Returns** - `view_matrix` (const dmVMath::Matrix4&) ### HConstant *Type:* TYPEDEF Shader constant handle ### HFont *Type:* TYPEDEF Font map handle ### HLightPrototype *Type:* TYPEDEF Light prototype handle. Used to create light instances. ### HMaterial *Type:* TYPEDEF Material instance handle ### HNamedConstantBuffer *Type:* TYPEDEF Shader constant buffer handle. Holds name and values for a constant. ### HRenderContext *Type:* TYPEDEF The render context ### HRenderListDispatch *Type:* TYPEDEF Render dispatch function handle. ### HSampler *Type:* TYPEDEF Sampler handle ### IterateNamedConstants *Type:* FUNCTION Iterates over the constants **Parameters** - `buffer` (dmRender::HNamedConstantBuffer) - the constants buffer - `callback` (IterateNamedConstantsFn) - the callback function - `ctx` (void*) - the callback context ### IterateNamedConstantsFn *Type:* TYPEDEF **Parameters** - `name_hash` (dmhash_t) - `ctx` (void*) ### NewConstant *Type:* FUNCTION Creates a shader program constant **Parameters** - `name_hash` (dmhash_t) - the name of the material constant **Returns** - `constant` (dmRender::HConstant) - the constant ### NewMaterial *Type:* FUNCTION **Parameters** - `render_context` (dmRender::HContext) - Render context - `program` (dmGraphics::HProgram) **Returns** - `new_material` (dmRender::HMaterial) ### NewNamedConstantBuffer *Type:* FUNCTION Allocates a named constant buffer **Returns** - `buffer` (dmRender::HNamedConstantBuffer) - the constants buffer ### RemoveNamedConstant *Type:* FUNCTION Removes a named constant from the buffer **Parameters** - `buffer` (dmRender::HNamedConstantBuffer) - the constants buffer - `name_hash` (dmhash_t) - the name of the constant ### RenderListAlloc *Type:* FUNCTION Allocates an array of render entries **Notes** - Do not store a pointer into this array, as they're reused next frame **Parameters** - `context` (dmRender::HRenderContext) - the context - `entries` (uint32_t) - the number of entries to allocate **Returns** - `array` (dmRender::RenderListEntry*) - the render list entry array ### RenderListDispatchFn *Type:* TYPEDEF Render dispatch function callback. **Parameters** - `params` (dmRender::RenderListDispatchParams) - the params ### RenderListDispatchParams *Type:* STRUCT Render dispatch function callback. **Members** - `m_Context` (dmRender::HRenderContext) - the context - `m_UserData` (void*) - the callback user data (registered with RenderListMakeDispatch()) - `m_Operation` (dmRender::RenderListOperation) - the operation - `m_Buf` (dmRender::RenderListEntry) - the render entry array - `m_Begin` (uint32_t*) - the start of the render batch. contains index into the m_Buf array - `m_End` (uint32_t*) - the end of the render batch. Loop while "m_Begin != m_End" ### RenderListEntry *Type:* FUNCTION Represents a renderable object (e.g. a single sprite) The renderer will (each frame) collect all entries with the current material tag, then batch these objects together. Batching is done based on the batch key and Z value (or order for GUI nodes) The caller will also register a callback function where the batched entries will be returned. Each callback then represents a draw call, and will register a RenderObject **Parameters** - `m_WorldPosition` (dmVMath::Point3) - the world position of the object - `m_UserData` (uint64_t) - user data (available in the render dispatch callback) - `m_Order` (uint32_t) - the order to sort on (used if m_MajorOrder != RENDER_ORDER_WORLD) - `m_BatchKey` (uint32_t) - the batch key to sort on (note: only 48 bits are currently used by renderer) - `m_TagListKey` (uint32_t) - the key to the list of material tags - `m_FrustumHash` (uint32_t) - Last combined frustum cull key (note: engine internal use only!) - `m_MinorOrder` (uint32_t:4) - used to sort within a batch - `m_MajorOrder` (uint32_t:2) - If RENDER_ORDER_WORLD, then sorting is done based on the world position. Otherwise the sorting uses the m_Order value directly. - `m_Dispatch` (uint32_t:8) - The dispatch function callback (dmRender::HRenderListDispatch) - `m_Visibility` (uint32_t:1) - Visibility flag. Used for frustrum culling. See enum Visibility ### RenderListMakeDispatch *Type:* FUNCTION Register a render dispatch function **Parameters** - `context` (dmRender::HRenderContext) - the context - `dispatch_fn` (dmRender::RenderListDispatchFn) - the render batch callback function - `visibility_fn` (dmRender::RenderListVisibilityFn) - the render list visibility callback function. May be 0 - `user_data` (void*) - userdata to the callback **Returns** - `dispatch` (dmRender::HRenderListDispatch) - the render dispatch function handle ### RenderListOperation *Type:* ENUM Render batch callback states **Members** - `RENDER_LIST_OPERATION_BEGIN` - `RENDER_LIST_OPERATION_BATCH` - `RENDER_LIST_OPERATION_END` ### RenderListSubmit *Type:* FUNCTION Adds a render object to the current render frame **Parameters** - `context` (dmRender::HRenderContext) - the context - `begin` (dmRender::RenderListEntry*) - the start of the array - `end` (dmRender::RenderListEntry*) - the end of the array (i.e. "while begin!=end: *begin ..."") ### RenderListVisibilityFn *Type:* TYPEDEF Render visibility function callback. **Parameters** - `params` (dmRender::RenderListVisibilityParams) - the params ### RenderListVisibilityParams *Type:* STRUCT Visibility dispatch function callback. **Members** - `m_UserData` (void*) - the callback user data (registered with RenderListMakeDispatch()) - `m_Entries` (dmRender::RenderListEntry) - the render entry array - `m_NumEntries` (uint32_t) - the number of render entries in the array ### RenderObject *Type:* STRUCT Render objects represent an actual draw call **Members** - `m_Constants` (dmRender::HConstant[) - ] the shader constants - `m_WorldTransform` (dmVMath::Matrix4) - the world transform (usually identity for batched objects) - `m_TextureTransform` (dmVMath::Matrix4) - the texture transform - `m_VertexBuffer` (dmGraphics::HVertexBuffer) - the vertex buffer - `m_VertexDeclaration` (dmGraphics::HVertexDeclaration) - the vertex declaration - `m_IndexBuffer` (dmGraphics::HIndexBuffer) - the index buffer - `m_Material` (dmRender::HMaterial) - the material - `m_Textures` (dmGraphics::HTexture[) - ] the textures - `m_PrimitiveType` (dmGraphics::PrimitiveType) - the primitive type - `m_IndexType` (dmGraphics::Type) - the index type (16/32 bit) - `m_SourceBlendFactor` (dmGraphics::BlendFactor) - the source blend factor - `m_DestinationBlendFactor` (dmGraphics::BlendFactor) - the destination blend factor - `m_StencilTestParams` (dmRender::StencilTestParams) - the stencil test params - `m_VertexStart` (uint32_t) - the vertex start - `m_VertexCount` (uint32_t) - the vertex count - `m_SetBlendFactors` (uint8_t:1) - use the blend factors - `m_SetStencilTest` (uint8_t:1) - use the stencil test ### RenderOrder *Type:* ENUM Render order **Members** - `RENDER_ORDER_WORLD` - Used by game objects - `RENDER_ORDER_AFTER_WORLD` - Used by gui ### Result *Type:* ENUM **Members** - `RESULT_OK` - `RESULT_INVALID_CONTEXT` - `RESULT_OUT_OF_RESOURCES` - `RESULT_BUFFER_IS_FULL` - `RESULT_INVALID_PARAMETER` ### SetConstantLocation *Type:* FUNCTION Sets the shader program constant location **Parameters** - `constant` (dmRender::HConstant) - The shader constant - `location` (dmGraphics::HUniformLocation) - the location ### SetConstantType *Type:* FUNCTION Sets the type of the constant **Parameters** - `constant` (dmRender::HConstant) - The shader constant - `type` (dmRenderDDF::MaterialDesc::ConstantType) - the type of the constant ### SetConstantValues *Type:* FUNCTION Sets the shader program constant values **Parameters** - `constant` (dmRender::HConstant) - The shader constant - `values` (dmVMath::Vector4*) - the array values - `num_values` (uint32_t) - the array size (number of Vector4's) **Returns** - `result` (dmRender::Result) - the result ### SetMaterialSampler *Type:* FUNCTION **Parameters** - `material` (dmRender::HMaterial) - `name_hash` (dmhash_t) - `unit` (uint32_t) - `u_wrap` (dmGraphics::TextureWrap) - `v_wrap` (dmGraphics::TextureWrap) - `min_filter` (dmGraphics::TextureFilter) - `mag_filter` (dmGraphics::TextureFilter) - `max_anisotropy` (float) **Returns** - `is_succeed` (bool) ### SetMaterialTags *Type:* FUNCTION **Parameters** - `material` (dmRender::Material) - `tag_count` (uint32_t) - `tags` (const dmhash_t*) ### SetNamedConstant *Type:* FUNCTION Sets one or more named constants to the buffer **Parameters** - `buffer` (dmRender::HNamedConstantBuffer) - the constants buffer - `name_hash` (dmhash_t) - the name of the constant - `values` (dmVMath::Vector4*) - the values - `num_values` (uint32_t) - the number of values ### SetNamedConstant *Type:* FUNCTION Sets one or more named constants to the buffer with a specified data type. Currently only dmRenderDDF::MaterialDesc::CONSTANT_TYPE_USER and dmRenderDDF::MaterialDesc::CONSTANT_TYPE_USER_MATRIX4 are supported. **Parameters** - `buffer` (dmRender::HNamedConstantBuffer) - the constants buffer - `name_hash` (dmhash_t) - the name of the constant - `values` (dmVMath::Vector4*) - the values - `num_values` (uint32_t) - the number of values - `constant_type` (dmRenderDDF::MaterialDesc::ConstantType) - The constant type ### SetNamedConstantAtIndex *Type:* FUNCTION Sets a named constant in the buffer at a specific index **Parameters** - `buffer` (dmRender::HNamedConstantBuffer) - the constants buffer - `name_hash` (dmhash_t) - the name of the constant - `value` (dmVMath::Vector4) - the value - `value_index` (uint32_t) - the index of the value to set **Returns** - `result` (Result) - the result ### SetNamedConstants *Type:* FUNCTION Sets a list of named constants to the buffer **Parameters** - `buffer` (dmRender::HNamedConstantBuffer) - the constants buffer - `constants` (dmRender::HConstant*) - the constants - `num_constants` (uint32_t) - the number of constants ### StencilTestParams *Type:* STRUCT Struct holding stencil operation setup **Members** - `m_Func` (dmGraphics::CompareFunc) - the compare function - `m_OpSFail` (dmGraphics::StencilOp) - the stencil fail operation - `m_OpDPFail` (dmGraphics::StencilOp) - the depth pass fail operation - `m_OpDPPass` (dmGraphics::StencilOp) - the depth pass pass operation - `m_Ref` (uint8_t) - `m_RefMask` (uint8_t) - `m_BufferMask` (uint8_t) - `m_ColorBufferMask` (uint8_t:4) - `m_ClearBuffer` (uint8_t:1) ### Visibility *Type:* ENUM Visibility status **Members** - `VISIBILITY_NONE` - `VISIBILITY_FULL` # Resource {#apis:engine-resource-src-dmsdk-resource-resource-hpp} **Namespace:** `dmResource` **Language:** C++ **Type:** Defold C++ **File:** `resource.hpp` **Source:** `engine/resource/src/dmsdk/resource/resource.hpp` **Include:** `dmsdk/resource/resource.hpp` Functions for managing resource and resource types ## API ### AddFile *Type:* FUNCTION Adds a file to the resource system Any request for this path will go through any existing mounts first. If you wish to provide file overrides, please use the LiveUpdate feature for that. The file isn't persisted between sessions. **Parameters** - `factory` (dmResource::HFactory) - Factory handle - `path` (const char*) - The path of the resource - `size` (uint32_t) - The size of the resource (in bytes) - `resource` (const void*) - The resource payload **Returns** - `RESULT_OK` (dmResource::Result) - on success. ### CreateResource *Type:* FUNCTION Creates and inserts a resource into the factory **Notes** - The input data pointer is not stored - The reference count is 1, so make sure it's destruction is handled **Parameters** - `factory` (dmResource::HFactory) - Factory handle - `name` (dmhash_t) - Resource name - `data` (void*) - Resource data - `data_size` (uint32_t) - Resource data size - `resource` (void**) - (out) Created resource **Returns** - `result` (dmResource::Result) - RESULT_OK on success ### FDecryptResource *Type:* TYPEDEF Decrypts a file **Notes** - Currently, the function requires the final resource to be the same length (or less) **Parameters** - `buffer` (void*) - The input/output buffer - `buffer_len` (uint32_t) - The size of the buffer (in bytes) **Returns** - `RESULT_OK` - on success ### FResourceCreate *Type:* FUNCTION **Notes** - Deprecated in favor of ResourceTypeSetCreateFn ### FResourceDestroy *Type:* FUNCTION **Notes** - Deprecated in favor of ResourceTypeSetDestroyFn ### FResourcePostCreate *Type:* FUNCTION **Notes** - Deprecated in favor of ResourceTypeSetPostCreateFn ### FResourcePreload *Type:* FUNCTION **Notes** - Deprecated in favor of ResourceTypeSetPreloadFn ### FResourceRecreate *Type:* FUNCTION **Notes** - Deprecated in favor of ResourceTypeSetRecreateFn ### Get *Type:* FUNCTION Get a resource from factory **Parameters** - `factory` (dmResource::HFactory) - Factory handle - `path` (const char*) - Resource path - `resource` (void**) - (out) Created resource **Returns** - `result` (dmResource::Result) - RESULT_OK on success ### Get *Type:* FUNCTION Get a loaded resource from factory **Parameters** - `factory` (dmResource::HFactory) - Factory handle - `path_hash` (const char*) - Resource path hash - `resource` (void**) - (out) Created resource **Returns** - `result` (dmResource::Result) - RESULT_OK on success ### GetCanonicalPath *Type:* FUNCTION Gets the normalized resource path: "/my//icon.texturec" -> "/my/icon.texturec". "my/icon.texturec" -> "/my/icon.texturec". **Parameters** - `path` (const char*) - the relative dir of the resource - `buf` (char*) - (out) the output of the normalization - `buf_len` (uint32_t) - the size of the output buffer **Returns** - `length` (uint32_t) - the length of the output string ### GetPath *Type:* FUNCTION Returns the canonical path hash of a resource **Parameters** - `factory` (dmResource::HFactory) - Factory handle - `resource` (const void*) - Resource - `hash` (uint64_t*) - Returned hash **Returns** - `RESULT_OK` - on success ### GetTypeFromExtension *Type:* FUNCTION Get type from extension **Parameters** - `factory` (dmResource::HFactory) - Factory handle - `extension` (const char*) - File extension, without leading "." character. E.g. "ttf" - `type` (HResourceType*) - returned type is successful **Returns** - `result` (dmResult::Result) - RESULT_OK on success ### GetTypeFromExtensionHash *Type:* FUNCTION Get type from extension hash **Parameters** - `factory` (dmResource::HFactory) - Factory handle - `extension_hash` (const char*) - Hash of file extension, without leading "." character. E.g. hash("ttf") - `type` (HResourceType*) - returned type is successful **Returns** - `result` (dmResult::Result) - RESULT_OK on success ### GetWithExt *Type:* FUNCTION Get (load) a resource from factory **Parameters** - `factory` (dmResource::HFactory) - Factory handle - `path` (const char*) - Resource path - `ext` (const char*) - Resource extension. Must match the extension of the path - `resource` (void**) - (out) Created resource **Returns** - `result` (dmResource::Result) - RESULT_OK on success. RESULT_INVALID_FILE_EXTENSION if the path extension doesn't match the required extension. ### GetWithExt *Type:* FUNCTION Get a loaded resource from factory **Parameters** - `factory` (dmResource::HFactory) - Factory handle - `path_hash` (const char*) - Resource path hash - `ext_hash` (const char*) - Resource extension hash. Must match the extension of the path. - `resource` (void**) - (out) Created resource **Returns** - `result` (dmResource::Result) - RESULT_OK on success. RESULT_INVALID_FILE_EXTENSION if the path extension doesn't match the required extension. ### PreloadHint *Type:* FUNCTION Hint the preloader what to load before Create is called on the resource. The resources are not guaranteed to be loaded before Create is called. This function can be called from a worker thread. **Parameters** - `factory` (dmResource::HResourcePreloadHintInfo) - Preloader handle - `name` (const char*) - Resource name **Returns** - `result` (bool) - if successfully invoking preloader. ### RegisterResourceDecryptionFunction *Type:* FUNCTION Registers a custom resource decryption function **Parameters** - `decrypt_resource` (dmResource::FDecryptResource) - The decryption function ### RegisterResourceReloadedCallback *Type:* FUNCTION Function called when a resource has been reloaded. **Parameters** - `factory` (dmResource::HFactory) - Handle of the factory to which the callback will be registered - `callback` (dmResource::FResourceReloadedCallback) - Callback function to register - `user_data` (void*) - User data that to ### RegisterType *Type:* FUNCTION **Notes** - Deprecated in favor of ResourceRegisterTypeCreatorDesc ### Release *Type:* FUNCTION Release resource **Parameters** - `factory` (dmResource::HFactory) - Factory handle - `resource` (void*) - Resource pointer ### RemoveFile *Type:* FUNCTION Removes a previously registered file from the resource system **Parameters** - `factory` (dmResource::HFactory) - Factory handle - `path` (const char*) - The path of the resource **Returns** - `RESULT_OK` (dmResource::Result) - on success. ### SetupType *Type:* FUNCTION Setup function pointers and context for a resource type **Notes** - C++ Helper function. Deprecated in favor of ResourceRegisterTypeCreatorDesc et al # Resource {#apis:engine-resource-src-dmsdk-resource-resource_gen-hpp} **Namespace:** `dmResource` **Language:** C++ **Type:** Defold C++ **File:** `resource_gen.hpp` **Source:** `engine/resource/src/dmsdk/resource/resource_gen.hpp` **Include:** `dmsdk/resource/resource_gen.hpp` Functions for managing resource types. ## API ### AddFile *Type:* FUNCTION Adds a file to the resource system Any request for this path will go through any existing mounts first. If you wish to provide file overrides, please use the LiveUpdate feature for that. The file isn't persisted between sessions. **Parameters** - `factory` (HResourceFactory) - Factory handle - `path` (const char*) - The path of the resource - `size` (uint32_t) - The size of the resource (in bytes) - `resource` (const void*) - The resource payload **Returns** - `result` (ResourceResult) - RESULT_OK on success ### DM_DECLARE_RESOURCE_TYPE *Type:* MACRO Declare and register new resource type to the engine. This macro is used to declare the resource type callback functions used by the engine to communicate with the extension. **Examples** Register a new type: ``` #include #include static ResourceResult MyResourceTypeScriptCreate(const ResourceCreateParams* params) {} static ResourceResult MyResourceTypeScriptDestroy(const ResourceDestroyParams* params) {} static ResourceResult MyResourceTypeScriptRecreate(const ResourceRereateParams* params) {} struct MyContext { // ... }; static ResourceResult RegisterResourceTypeBlob(HResourceTypeRegisterContext ctx, HResourceType type) { // The engine.cpp creates the contexts for our built in types. // Here we register a custom type MyContext* context = new MyContext; ResourceTypeSetContext(type, (void*)context); ResourceTypeSetCreateFn(type, MyResourceTypeScriptCreate); ResourceTypeSetDestroyFn(type, MyResourceTypeScriptDestroy); ResourceTypeSetRecreateFn(type, MyResourceTypeScriptRecreate); } static ResourceResult DeregisterResourceTypeBlob(ResourceTypeRegisterContext& ctx) { MyContext** context = (MyContext*)ResourceTypeGetContext(type); delete *context; } DM_DECLARE_RESOURCE_TYPE(ResourceTypeBlob, "blobc", RegisterResourceTypeBlob, DeregisterResourceTypeBlob); ``` ### FReloadedCallback *Type:* FUNCTION Function called when a resource has been reloaded. ### FResourceDecrypt *Type:* TYPEDEF Encrypts a resource in-place **Parameters** - `buffer` (void*) - The input/output buffer - `buffer_len` (uint32_t) - The size of the buffer (in bytes) **Returns** - `RESULT_OK` - on success ### FResourceReloadedCallback *Type:* FUNCTION Function called when a resource has been reloaded. ### Get *Type:* FUNCTION Get a resource from factory **Parameters** - `factory` (HResourceFactory) - Factory handle - `name` (const char*) - Resource name - `resource` (void**) - Created resource **Returns** - `result` (ResourceResult) - RESULT_OK on success ### GetByHash *Type:* FUNCTION Get a resource from factory **Parameters** - `factory` (HResourceFactory) - Factory handle - `name` (dmhash_t) - Resource name - `resource` (void**) - Created resource **Returns** - `result` (ResourceResult) - RESULT_OK on success ### GetDescriptor *Type:* FUNCTION Get resource descriptor from resource (name) **Parameters** - `factory` (HResourceFactory) - Factory handle - `path` (dmhash_t) - Resource path - `descriptor` (HResourceDescriptor*) - Returned resource descriptor **Returns** - `result` (ResourceResult) - RESULT_OK on success ### GetDescriptorByHash *Type:* FUNCTION Get resource descriptor from resource (name) **Parameters** - `factory` (HResourceFactory) - Factory handle - `path_hash` (dmhash_t) - Resource path hash - `descriptor` (HResourceDescriptor*) - Returned resource descriptor **Returns** - `result` (ResourceResult) - RESULT_OK on success ### GetPath *Type:* FUNCTION Returns the canonical path hash of a resource **Parameters** - `factory` (HResourceFactory) - Factory handle - `resource` (void*) - The resource pointer - `hash` (dmhash_t*) - (out) The path hash of the resource **Returns** - `result` (ResourceResult) - RESULT_OK on success ### GetRaw *Type:* FUNCTION Get raw resource data. Unregistered resources can be loaded with this function. If successful, the returned resource data must be deallocated with free() **Parameters** - `factory` (HResourceFactory) - Factory handle - `name` (dmhash_t) - Resource name - `resource` (void**) - Created resource - `resource_size` (uint32_t*) - Resource size **Returns** - `result` (ResourceResult) - RESULT_OK on success ### HDescriptor *Type:* TYPEDEF Holds information about a currently loaded resource. ### HFactory *Type:* TYPEDEF Resource factory handle. Holds references to all currently loaded resources. ### HPreloadHintInfo *Type:* TYPEDEF Holds information about preloading resources ### HResourceDescriptor *Type:* TYPEDEF Holds information about a currently loaded resource. ### HResourceFactory *Type:* TYPEDEF Resource factory handle. Holds references to all currently loaded resources. ### HResourcePreloadHintInfo *Type:* TYPEDEF Holds information about preloading resources ### HResourceType *Type:* TYPEDEF Represents a resource type, with a context and type functions for creation and destroying a resource. ### HResourceTypeContext *Type:* TYPEDEF Holds the resource types, as well as extra in engine contexts that can be shared across type functions. ### PreloadHint *Type:* FUNCTION Hint the preloader what to load before Create is called on the resource. The resources are not guaranteed to be loaded before Create is called. This function can be called from a worker thread. **Parameters** - `preloader` (dmResource::HResourcePreloadHintInfo) - Preloader handle - `path` (const char*) - Resource path **Returns** - `result` (bool) - if successfully invoking preloader. ### Release *Type:* FUNCTION Release resource **Notes** - Decreases ref count by 1. If it reaches 0, the resource destroy function is called. **Parameters** - `factory` (HResourceFactory) - Factory handle - `resource` (void*) - Resource pointer ### RemoveFile *Type:* FUNCTION Removes a previously registered file from the resource system **Parameters** - `factory` (HResourceFactory) - Factory handle - `path` (const char*) - The path of the resource **Returns** - `result` (ResourceResult) - RESULT_OK on success ### ResourceAddFile *Type:* FUNCTION Adds a file to the resource system Any request for this path will go through any existing mounts first. If you wish to provide file overrides, please use the LiveUpdate feature for that. The file isn't persisted between sessions. **Parameters** - `factory` (HResourceFactory) - Factory handle - `path` (const char*) - The path of the resource - `size` (uint32_t) - The size of the resource (in bytes) - `resource` (const void*) - The resource payload **Returns** - `result` (ResourceResult) - RESULT_OK on success ### ResourceCreateParams *Type:* FUNCTION Parameters to ResourceCreate function of the resource type ### ResourceDestroyParams *Type:* FUNCTION Parameters to ResourceDestroy function of the resource type ### ResourceGet *Type:* FUNCTION Get a resource from factory **Parameters** - `factory` (HResourceFactory) - Factory handle - `name` (const char*) - Resource name - `resource` (void**) - Created resource **Returns** - `result` (ResourceResult) - RESULT_OK on success ### ResourceGetByHash *Type:* FUNCTION Get a resource from factory **Parameters** - `factory` (HResourceFactory) - Factory handle - `name` (dmhash_t) - Resource name - `resource` (void**) - Created resource **Returns** - `result` (ResourceResult) - RESULT_OK on success ### ResourceGetPath *Type:* FUNCTION Returns the canonical path hash of a resource **Parameters** - `factory` (HResourceFactory) - Factory handle - `resource` (void*) - The resource pointer - `hash` (dmhash_t*) - (out) The path hash of the resource **Returns** - `result` (ResourceResult) - RESULT_OK on success ### ResourceGetRaw *Type:* FUNCTION Get raw resource data. Unregistered resources can be loaded with this function. If successful, the returned resource data must be deallocated with free() **Parameters** - `factory` (HResourceFactory) - Factory handle - `name` (dmhash_t) - Resource name - `resource` (void**) - Created resource - `resource_size` (uint32_t*) - Resource size **Returns** - `result` (ResourceResult) - RESULT_OK on success ### ResourcePostCreateParams *Type:* FUNCTION Parameters to ResourcePostCreate function of the resource type ### ResourcePreloadHint *Type:* FUNCTION Hint the preloader what to load before Create is called on the resource. The resources are not guaranteed to be loaded before Create is called. This function can be called from a worker thread. **Parameters** - `preloader` (dmResource::HResourcePreloadHintInfo) - Preloader handle - `path` (const char*) - Resource path **Returns** - `result` (bool) - if successfully invoking preloader. ### ResourcePreloadParams *Type:* FUNCTION Parameters to ResourcePreload function of the resource type ### ResourceRecreateParams *Type:* FUNCTION Parameters to ResourceRecreate function of the resource type ### ResourceRegisterDecryptionFunction *Type:* FUNCTION Registers a custom resource decryption function **Parameters** - `decrypt_resource` (dmResource::FDecryptResource) - The decryption function ### ResourceRelease *Type:* FUNCTION Release resource **Notes** - Decreases ref count by 1. If it reaches 0, the resource destroy function is called. **Parameters** - `factory` (HResourceFactory) - Factory handle - `resource` (void*) - Resource pointer ### ResourceReloadedParams *Type:* FUNCTION Parameters to ResourceReloaded function of the resource type ### ResourceReloadedParams *Type:* FUNCTION Parameters to ResourceReloaded function of the resource type ### ResourceRemoveFile *Type:* FUNCTION Removes a previously registered file from the resource system **Parameters** - `factory` (HResourceFactory) - Factory handle - `path` (const char*) - The path of the resource **Returns** - `result` (ResourceResult) - RESULT_OK on success ### ResourceResult *Type:* ENUM ResourceResult **Members** - `RESOURCE_RESULT_OK` - `RESOURCE_RESULT_INVALID_DATA` - `RESOURCE_RESULT_DDF_ERROR` - `RESOURCE_RESULT_RESOURCE_NOT_FOUND` - `RESOURCE_RESULT_MISSING_FILE_EXTENSION` - `RESOURCE_RESULT_ALREADY_REGISTERED` - `RESOURCE_RESULT_INVAL` - `RESOURCE_RESULT_UNKNOWN_RESOURCE_TYPE` - `RESOURCE_RESULT_OUT_OF_MEMORY` - `RESOURCE_RESULT_IO_ERROR` - `RESOURCE_RESULT_NOT_LOADED` - `RESOURCE_RESULT_OUT_OF_RESOURCES` - `RESOURCE_RESULT_STREAMBUFFER_TOO_SMALL` - `RESOURCE_RESULT_FORMAT_ERROR` - `RESOURCE_RESULT_CONSTANT_ERROR` - `RESOURCE_RESULT_NOT_SUPPORTED` - `RESOURCE_RESULT_RESOURCE_LOOP_ERROR` - `RESOURCE_RESULT_PENDING` - `RESOURCE_RESULT_INVALID_FILE_EXTENSION` - `RESOURCE_RESULT_VERSION_MISMATCH` - `RESOURCE_RESULT_SIGNATURE_MISMATCH` - `RESOURCE_RESULT_UNKNOWN_ERROR` ### ResourceTypeCreatorDescBufferSize *Type:* FUNCTION Resource type creator desc byte size declaration. The registered description data passeed to ResourceRegisterTypeCreatorDesc must be of at least this size. ### Result *Type:* ENUM ResourceResult **Members** - `RESOURCE_RESULT_OK` - `RESOURCE_RESULT_INVALID_DATA` - `RESOURCE_RESULT_DDF_ERROR` - `RESOURCE_RESULT_RESOURCE_NOT_FOUND` - `RESOURCE_RESULT_MISSING_FILE_EXTENSION` - `RESOURCE_RESULT_ALREADY_REGISTERED` - `RESOURCE_RESULT_INVAL` - `RESOURCE_RESULT_UNKNOWN_RESOURCE_TYPE` - `RESOURCE_RESULT_OUT_OF_MEMORY` - `RESOURCE_RESULT_IO_ERROR` - `RESOURCE_RESULT_NOT_LOADED` - `RESOURCE_RESULT_OUT_OF_RESOURCES` - `RESOURCE_RESULT_STREAMBUFFER_TOO_SMALL` - `RESOURCE_RESULT_FORMAT_ERROR` - `RESOURCE_RESULT_CONSTANT_ERROR` - `RESOURCE_RESULT_NOT_SUPPORTED` - `RESOURCE_RESULT_RESOURCE_LOOP_ERROR` - `RESOURCE_RESULT_PENDING` - `RESOURCE_RESULT_INVALID_FILE_EXTENSION` - `RESOURCE_RESULT_VERSION_MISMATCH` - `RESOURCE_RESULT_SIGNATURE_MISMATCH` - `RESOURCE_RESULT_UNKNOWN_ERROR` # Script {#apis:engine-script-src-dmsdk-script-script-h} **Namespace:** `dmScript` **Language:** C++ **Type:** Defold C++ **File:** `script.h` **Source:** `engine/script/src/dmsdk/script/script.h` **Include:** `dmsdk/script/script.h` Built-in scripting functions. ## API ### CheckHash *Type:* FUNCTION Check if the value in the supplied index on the lua stack is a hash. **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `value` (hash) - The hash value ### CheckHashOrString *Type:* FUNCTION Check if the value in the supplied index on the lua stack is a hash or string. If it is a string, it gets hashed on the fly **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `value` (hash) - The hash value ### CheckMatrix4 *Type:* FUNCTION Check if the value in the supplied index on the lua stack is a dmVMath::Matrix4. **Notes** - throws a luaL_error if it's not the correct type **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `matrix` (dmVMath::Matrix4*) - The pointer to the value ### CheckQuat *Type:* FUNCTION Check if the value in the supplied index on the lua stack is a dmVMath::Quat. **Notes** - throws a luaL_error if it's not the correct type **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `quat` (dmVMath::Quat*) - The pointer to the value ### CheckTable *Type:* FUNCTION Serialize a table to a buffer Supported types: LUA_TBOOLEAN, LUA_TNUMBER, LUA_TSTRING, Point3, Vector3, Vector4 and Quat Keys must be strings **Parameters** - `L` (lua_State*) - Lua state - `buffer` (char*) - Buffer that will be written to (must be DM_ALIGNED(16)) - `buffer_size` (uint32_t) - Buffer size - `index` (int) - Index of the table **Returns** - `result` (uint32_t) - Number of bytes used in buffer ### CheckURL *Type:* FUNCTION Check if the value in the supplied index on the lua stack is a dmMessage::URL and returns it if so. **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `url` (dmMessage::URL*) - The pointer to the value ### CheckURL *Type:* FUNCTION Get the current game object URL **Parameters** - `L` (lua_State*) - Lua state - `out_url` (dmMessage::URL*) - where to store the result **Returns** - `result` (bool) - true if successful ### CheckVector3 *Type:* FUNCTION Check if the value in the supplied index on the lua stack is a dmVMath::Vector3. **Notes** - throws a luaL_error if it's not the correct type **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `vector3` (dmVMath::Vector3*) - The pointer to the value ### CheckVector4 *Type:* FUNCTION Check if the value in the supplied index on the lua stack is a dmVMath::Vector3. **Notes** - throws a luaL_error if it's not the correct type **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `vector4` (dmVMath::Vector4*) - The pointer to the value ### CreateCallback *Type:* FUNCTION Stores the current Lua state plus references to the script instance (self) and the callback. Expects SetInstance() to have been called prior to using this method. The allocated data is created on the Lua stack and references are made against the instances own context table. If the callback is not explicitly deleted with DestroyCallback() the references and data will stay around until the script instance is deleted. **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Lua stack index of the function **Returns** - `callback` (LuaCallbackInfo*) - Lua callback struct if successful, 0 otherwise **Examples** ``` static int SomeFunction(lua_State* L) // called from Lua { LuaCallbackInfo* cbk = dmScript::CreateCallback(L, 1); ... store the callback for later } static void InvokeCallback(LuaCallbackInfo* cbk) { lua_State* L = dmScript::GetCallbackLuaContext(cbk); DM_LUA_STACK_CHECK(L, 0); if (!dmScript::SetupCallback(callback)) { return; } lua_pushstring(L, "hello"); dmScript::PCall(L, 2, 0); // self + # user arguments dmScript::TeardownCallback(callback); dmScript::DestroyCallback(cbk); // only do this if you're not using the callback again } ``` ### DestroyCallback *Type:* FUNCTION Deletes the Lua callback **Parameters** - `cbk` (LuaCallbackInfo*) - Lua callback struct ### DM_LUA_ERROR *Type:* MACRO This macro will verify that the Lua stack size hasn't been changed before throwing a Lua error, which will long-jump out of the current function. This macro can only be used together with DM_LUA_STACK_CHECK and should be prefered over manual checking of the stack. **Parameters** - `fmt` (const char*) - Format string that contains error information. - `args` (...) - Format string args (variable arg list) **Examples** ``` static int ModuleFunc(lua_State* L) { DM_LUA_STACK_CHECK(L, 1); if (some_error_check(L)) { return DM_LUA_ERROR("some error message"); } lua_pushnumber(L, 42); return 1; } ``` ### DM_LUA_STACK_CHECK *Type:* MACRO Diff is the expected difference of the stack size. If luaL_error, or another function that executes a long-jump, is part of the executed code, the stack guard cannot be guaranteed to execute at the end of the function. In that case you should manually check the stack using lua_gettop. In the case of luaL_error, see DM_LUA_ERROR. **Parameters** - `L` (lua_State*) - lua state - `diff` (int) - Number of expected items to be on the Lua stack once this struct goes out of scope **Examples** ``` DM_LUA_STACK_CHECK(L, 1); lua_pushnumber(L, 42); ``` ### GetCallbackLuaContext *Type:* FUNCTION Gets the Lua context from a callback struct **Parameters** - `cbk` (LuaCallbackInfo*) - Lua callback struct **Returns** - `L` (lua_State*) - Lua state ### GetInstance *Type:* FUNCTION Retrieve current script instance from the global table and place it on the top of the stack, only valid when set. (see dmScript::GetMainThread) **Parameters** - `L` (lua_State*) - lua state ### GetLuaState *Type:* FUNCTION Retrieve Lua state from the context **Parameters** - `context` (HContext) - the script context **Returns** - `state` (lua_State*) - the lua state ### GetMainThread *Type:* FUNCTION Retrieve the main thread lua state from any lua state (main thread or coroutine). **Parameters** - `L` (lua_State*) - lua state **Returns** - `lua_State` (lua_State*) - the main thread lua state **Examples** How to create a Lua callback ``` dmScript::LuaCallbackInfo* g_MyCallbackInfo = 0; static void InvokeCallback(dmScript::LuaCallbackInfo* cbk) { if (!dmScript::IsCallbackValid(cbk)) return; lua_State* L = dmScript::GetCallbackLuaContext(cbk); DM_LUA_STACK_CHECK(L, 0) if (!dmScript::SetupCallback(cbk)) { dmLogError("Failed to setup callback"); return; } lua_pushstring(L, "Hello from extension!"); lua_pushnumber(L, 76); dmScript::PCall(L, 3, 0); // instance + 2 dmScript::TeardownCallback(cbk); } static int Start(lua_State* L) { DM_LUA_STACK_CHECK(L, 0); g_MyCallbackInfo = dmScript::CreateCallback(L, 1); return 0; } static int Update(lua_State* L) { DM_LUA_STACK_CHECK(L, 0); static int count = 0; if( count++ == 5 ) { InvokeCallback(g_MyCallbackInfo); if (g_MyCallbackInfo) dmScript::DestroyCallback(g_MyCallbackInfo); g_MyCallbackInfo = 0; } return 0; } ``` ### GetStringFromHashOrString *Type:* FUNCTION Gets as good as possible printable string from a hash or string **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value - `buffer` (char*) - buffer receiving the value - `buffer_length` (uint32_t) - the buffer length **Returns** - `string` (const char*) - Returns buffer. If buffer is non null, it will always contain a null terminated string. "" if the hash could not be looked up. ### HContext *Type:* TYPEDEF The script context ### IsCallbackValid *Type:* FUNCTION Check if Lua callback is valid. **Parameters** - `cbk` (LuaCallbackInfo*) - Lua callback struct ### IsHash *Type:* FUNCTION Check if the value at #index is a hash **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `result` (bool) - true if the value at #index is a hash ### IsInstanceValid *Type:* FUNCTION Check if the script instance in the lua state is valid. The instance is assumed to have been previously set by dmScript::SetInstance. **Parameters** - `L` (lua_State*) - lua state **Returns** - `boolean` (bool) - Returns true if the instance is valid ### IsMatrix4 *Type:* FUNCTION Check if the value at #index is a dmVMath::Matrix4* **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `true` (bool) - if value at #index is a dmVMath::Matrix4* ### IsQuat *Type:* FUNCTION Check if the value at #index is a dmVMath::Quat* **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `true` (bool) - if value at #index is a dmVMath::Quat* ### IsURL *Type:* FUNCTION Check if the value at #index is a URL **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `result` (bool) - true if the value at #index is a URL ### IsVector3 *Type:* FUNCTION Check if the value at #index is a dmVMath::Vector3* **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `true` (bool) - if value at #index is a dmVMath::Vector3* ### IsVector4 *Type:* FUNCTION Check if the value at #index is a dmVMath::Vector4* **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `true` (bool) - if value at #index is a dmVMath::Vector4* ### JsonToLua *Type:* FUNCTION Convert a Json string to Lua table. **Notes** - Throws Lua error if it fails to parser the json **Parameters** - `L` (lua_State*) - lua state - `json` (const char*) - json string - `json_len` (size_t) - length of json string **Returns** - `int` (int) - 1 if it succeeds. Throws a Lua error if it fails ### LuaCallbackInfo *Type:* STRUCT callback info struct that will hold the relevant info needed to make a callback into Lua ### LuaToJson *Type:* FUNCTION Convert a Lua table to a Json string **Parameters** - `L` (lua_State*) - lua state - `json` (char**) - [out] Pointer to char*, which will receive a newly allocated string. Use free(). - `json_len` (size_t*) - length of json string **Returns** - `int` (int) - <0 if it fails. >=0 if it succeeds. ### PCall *Type:* FUNCTION This function wraps lua_pcall with the addition of specifying an error handler which produces a backtrace. In the case of an error, the error is logged and popped from the stack. **Parameters** - `L` (lua_State*) - lua state - `nargs` (int) - number of arguments - `nresult` (int) - number of results **Returns** - `error` (int) - error code from pcall ### PushDDF *Type:* FUNCTION Push DDF message to Lua stack **Parameters** - `L` (lua_State*) - the Lua state - `descriptor` (const dmDDF::Descriptor*) - field descriptor - `data` (const char*) - the message data (i.e. the message struct) - `pointers_are_offsets` (bool) - True if pointers are offsets ### PushHash *Type:* FUNCTION Push a hash value onto the supplied lua state, will increase the stack by 1. **Parameters** - `L` (lua_State*) - Lua state - `hash` (dmhash_t) - Hash value to push ### PushMatrix4 *Type:* FUNCTION Push a matrix4 value onto the Lua stack. Will increase the stack by 1. **Parameters** - `L` (lua_State*) - Lua state - `matrix` (dmVMath::Matrix4) - dmVMath::Matrix4 value to push ### PushQuat *Type:* FUNCTION Push a quaternion value onto Lua stack. Will increase the stack by 1. **Parameters** - `L` (lua_State*) - Lua state - `quat` (dmVMath::Quat) - dmVMath::Quat value to push ### PushURL *Type:* FUNCTION Push a URL value onto the supplied lua state, will increase the stack by 1. **Parameters** - `L` (lua_State*) - Lua state - `url` (dmMessage::URL&) - URL reference to push ### PushVector3 *Type:* FUNCTION Push a dmVMath::Vector3 value onto the supplied lua state, will increase the stack by 1. **Parameters** - `L` (lua_State*) - Lua state - `v` (dmVMath::Vector3) - Vector3 value to push ### PushVector4 *Type:* FUNCTION Push a dmVMath::Vector4 value onto the supplied lua state, will increase the stack by 1. **Parameters** - `L` (lua_State*) - Lua state - `v` (dmVMath::Vector4) - dmVMath::Vector4 value to push ### Ref *Type:* FUNCTION Creates and returns a reference, in the table at index t, for the object at the top of the stack (and pops the object). It also tracks number of global references kept. **Parameters** - `L` (lua_State*) - lua state - `table` (int) - table the lua table that stores the references. E.g LUA_REGISTRYINDEX **Returns** - `reference` (int) - the new reference ### RefInInstance *Type:* FUNCTION Creates a reference to the value at top of stack, the ref is done in the current instances context table. Expects SetInstance() to have been set with an value that has a meta table with META_GET_INSTANCE_CONTEXT_TABLE_REF method. **Parameters** - `L` (lua_State*) - Lua state **Returns** - `lua` (int) - ref to value or LUA_NOREF Lua stack on entry [-1] value Lua stack on exit ### RefInInstance *Type:* FUNCTION Resolves a url in string format into a dmMessage::URL struct. Special handling for: - "." returns the default socket + path - "#" returns default socket + path + fragment **Parameters** - `L` (lua_State*) - Lua state - `url` (const char*) - url - `out_url` (dmMessage::URL*) - where to store the result - `default_url` (dmMessage::URL*) - default url **Returns** - `result` (dmMessage::Result) - dmMessage::RESULT_OK if the conversion succeeded ### ResolveURL *Type:* FUNCTION Resolves the value in the supplied index on the lua stack to a URL. It long jumps (calls luaL_error) on failure. It also gets the current (caller) url if the a pointer is passed to out_default_url **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value - `out_url` (dmMessage::URL*) - where to store the result - `out_default_url` (dmMessage::URL*) - default URL used in the resolve, can be 0x0 (not used) **Returns** - `result` (int) - 0 if successful. Throws Lua error on failure ### SetInstance *Type:* FUNCTION Sets the current script instance Set the value on the top of the stack as the instance into the global table and pops it from the stack. (see dmScript::GetMainThread) **Parameters** - `L` (lua_State*) - lua state ### SetupCallback *Type:* FUNCTION The Lua stack after a successful call: ``` [-4] old instance [-3] context table [-2] callback [-1] self ``` In the event of an unsuccessful call, the Lua stack is unchanged **Parameters** - `cbk` (LuaCallbackInfo*) - Lua callback struct **Returns** - `true` (bool) - if the setup was successful ### TeardownCallback *Type:* FUNCTION Sets the previous instance Expects Lua stack: ``` [-2] old instance [-1] context table ``` Both values are removed from the stack **Parameters** - `cbk` (LuaCallbackInfo*) - Lua callback struct ### ToHash *Type:* FUNCTION Check if the value at #index is a hash **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `hash` (dmhash_t*) - pointer to hash or 0 if it's not a hash ### ToMatrix4 *Type:* FUNCTION Get the value at index as a dmVMath::Matrix4* **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `quat` (dmVMath::Matrix4*) - The pointer to the value, or 0 if not correct type ### ToQuat *Type:* FUNCTION Get the value at index as a dmVMath::Quat* **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `quat` (dmVMath::Quat*) - The pointer to the value, or 0 if not correct type ### ToURL *Type:* FUNCTION get the value at index as a dmMessage::URL* **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `hash` (dmhash_t*) - pointer to URL or 0 if it's not a URL ### ToVector3 *Type:* FUNCTION Get the value at index as a dmVMath::Vector3* **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `v` (dmVMath::Vector3*) - The pointer to the value, or 0 if not correct type ### ToVector4 *Type:* FUNCTION Get the value at index as a dmVMath::Vector4* **Parameters** - `L` (lua_State*) - Lua state - `index` (int) - Index of the value **Returns** - `v` (dmVMath::Vector4*) - The pointer to the value, or 0 if not correct type ### Unref *Type:* FUNCTION Releases reference ref from the table at index t (see luaL_ref). The entry is removed from the table, so that the referred object can be collected. It also decreases the number of global references kept **Parameters** - `L` (lua_State*) - lua state - `table` (int) - table the lua table that stores the references. E.g LUA_REGISTRYINDEX - `reference` (int) - the reference to the object ### UnrefInInstance *Type:* FUNCTION Deletes the instance local lua reference Expects SetInstance() to have been set with an value that has a meta table with META_GET_INSTANCE_CONTEXT_TABLE_REF method. **Parameters** - `L` (lua_State*) - Lua state - `ref` (int) - ref to value or LUA_NOREF Lua stack on entry Lua stack on exit ### UrlToString *Type:* FUNCTION Converts a URL into a readable string. Useful for e.g. error messages **Parameters** - `url` (dmMessage::URL*) - url - `buffer` (char*) - the output buffer - `buffer_size` (uint32_t) - the output buffer size **Returns** - `buffer` (const char*) - returns the passed in buffer # Sound {#apis:engine-sound-src-dmsdk-sound-sound-h} **Namespace:** `dmSound` **Language:** C++ **Type:** Defold C++ **File:** `sound.h` **Source:** `engine/sound/src/dmsdk/sound/sound.h` **Include:** `dmsdk/sound/sound.h` Functions for controlling the engine sound mixer from native extensions. ## API ### IsGroupMuted *Type:* FUNCTION Query group mute state **Parameters** - `group` (dmhash_t) - hash of the mixer group (e.g. hash("master")) **Returns** - `muted` (bool) - true if the mixer group is muted ### Result *Type:* ENUM **Members** - `RESULT_OK` - `RESULT_PARTIAL_DATA` - `RESULT_OUT_OF_SOURCES` - `RESULT_EFFECT_NOT_FOUND` - `RESULT_OUT_OF_INSTANCES` - `RESULT_RESOURCE_LEAK` - `RESULT_OUT_OF_BUFFERS` - `RESULT_INVALID_PROPERTY` - `RESULT_UNKNOWN_SOUND_TYPE` - `RESULT_INVALID_STREAM_DATA` - `RESULT_OUT_OF_MEMORY` - `RESULT_UNSUPPORTED` - `RESULT_DEVICE_NOT_FOUND` - `RESULT_OUT_OF_GROUPS` - `RESULT_NO_SUCH_GROUP` - `RESULT_NOTHING_TO_PLAY` - `RESULT_INIT_ERROR` - `RESULT_FINI_ERROR` - `RESULT_NO_DATA` - `RESULT_END_OF_STREAM` - `RESULT_DEVICE_LOST` - `RESULT_UNKNOWN_ERROR` ### SetGroupMute *Type:* FUNCTION Temporarily mute or restore an individual mixer group. **Parameters** - `group` (dmhash_t) - hash of the mixer group (e.g. hash("master")) - `mute` (bool) - true to mute, false to restore audio **Returns** - `result` (Result) - RESULT_OK on success ### ToggleGroupMute *Type:* FUNCTION Convenience toggle for SetGroupMute. **Parameters** - `group` (dmhash_t) - hash of the mixer group (e.g. hash("master")) **Returns** - `result` (Result) - RESULT_OK on success # b2d {#apis:b2d-lua} **Namespace:** `b2d` **Language:** Lua **Type:** Defold Lua **File:** `script_box2d.cpp` **Source:** `engine/gamesys/src/gamesys/scripts/box2d/script_box2d.cpp` Functions for interacting with Box2D. ## API ### b2Body *Type:* TYPEDEF Box2D body **Parameters** - `value` (userdata) ### b2d.get_body *Type:* FUNCTION Get the Box2D body from a collision object **Parameters** - `url` (string | hash | url) - the url to the game object collision component **Returns** - `body` (b2Body) - the body if successful. Otherwise nil. ### b2d.get_world *Type:* FUNCTION Get the Box2D world from the current collection **Returns** - `world` (b2World) - the world if successful. Otherwise nil. ### b2World *Type:* TYPEDEF Box2D world **Parameters** - `value` (userdata) # b2d.body {#apis:b2d.body-lua} **Namespace:** `b2d.body` **Language:** Lua **Type:** Defold Lua **File:** `script_box2d_body.cpp` **Source:** `engine/gamesys/src/gamesys/scripts/box2d/script_box2d_body.cpp` Functions for interacting with Box2D bodies. ## API ### b2Body *Type:* TYPEDEF Box2D body **Parameters** - `value` (userdata) ### b2d.body.apply_angular_impulse *Type:* FUNCTION Apply an angular impulse. **Parameters** - `body` (b2Body) - body - `impulse` (number) - impulse the angular impulse in units of kgmm/s ### b2d.body.apply_angular_impulse *Type:* FUNCTION Apply an angular impulse. **Parameters** - `body` (b2Body) - body - `impulse` (number) - impulse the angular impulse in units of kgmm/s ### b2d.body.apply_force *Type:* FUNCTION Apply a force at a world point. If the force is not applied at the center of mass, it will generate a torque and affect the angular velocity. This wakes up the body. **Parameters** - `body` (b2Body) - body - `force` (vector3) - the world force vector, usually in Newtons (N). - `point` (vector3) - the world position of the point of application. ### b2d.body.apply_force *Type:* FUNCTION Apply a force at a world point. If the force is not applied at the center of mass, it will generate a torque and affect the angular velocity. This wakes up the body. **Parameters** - `body` (b2Body) - body - `force` (vector3) - the world force vector, usually in Newtons (N). - `point` (vector3) - the world position of the point of application. ### b2d.body.apply_force_to_center *Type:* FUNCTION Apply a force to the center of mass. This wakes up the body. **Parameters** - `body` (b2Body) - body - `force` (vector3) - the world force vector, usually in Newtons (N). ### b2d.body.apply_force_to_center *Type:* FUNCTION Apply a force to the center of mass. This wakes up the body. **Parameters** - `body` (b2Body) - body - `force` (vector3) - the world force vector, usually in Newtons (N). ### b2d.body.apply_linear_impulse *Type:* FUNCTION Apply an impulse at a point. This immediately modifies the velocity. It also modifies the angular velocity if the point of application is not at the center of mass. This wakes up the body. **Parameters** - `body` (b2Body) - body - `impulse` (vector3) - the world impulse vector, usually in N-seconds or kg-m/s. - `point` (vector3) - the world position of the point of application. ### b2d.body.apply_linear_impulse *Type:* FUNCTION Apply an impulse at a point. This immediately modifies the velocity. It also modifies the angular velocity if the point of application is not at the center of mass. This wakes up the body. **Parameters** - `body` (b2Body) - body - `impulse` (vector3) - the world impulse vector, usually in N-seconds or kg-m/s. - `point` (vector3) - the world position of the point of application. ### b2d.body.apply_torque *Type:* FUNCTION Apply a torque. This affects the angular velocity without affecting the linear velocity of the center of mass. This wakes up the body. **Parameters** - `body` (b2Body) - body - `torque` (number) - torque about the z-axis (out of the screen), usually in N-m. ### b2d.body.apply_torque *Type:* FUNCTION Apply a torque. This affects the angular velocity without affecting the linear velocity of the center of mass. This wakes up the body. **Parameters** - `body` (b2Body) - body - `torque` (number) - torque about the z-axis (out of the screen), usually in N-m. ### b2d.body.B2_DYNAMIC_BODY *Type:* CONSTANT Dynamic body ### b2d.body.B2_DYNAMIC_BODY *Type:* CONSTANT Dynamic body ### b2d.body.B2_KINEMATIC_BODY *Type:* CONSTANT Kinematic body ### b2d.body.B2_KINEMATIC_BODY *Type:* CONSTANT Kinematic body ### b2d.body.B2_STATIC_BODY *Type:* CONSTANT Static (immovable) body ### b2d.body.B2_STATIC_BODY *Type:* CONSTANT Static (immovable) body ### b2d.body.dump *Type:* FUNCTION Print the body representation to the log output **Parameters** - `body` (b2Body) - body ### b2d.body.enable_sleep *Type:* FUNCTION You can disable sleeping on this body. If you disable sleeping, the body will be woken. **Parameters** - `body` (b2Body) - body - `enable` (boolean) - if false, the body will never sleep, and consume more CPU ### b2d.body.get_angle *Type:* FUNCTION Get the angle in radians. **Parameters** - `body` (b2Body) - body **Returns** - `angle` (number) - the current world rotation angle in radians. ### b2d.body.get_angular_damping *Type:* FUNCTION Get the angular damping of the body. **Parameters** - `body` (b2Body) - body **Returns** - `damping` (number) - the damping ### b2d.body.get_angular_damping *Type:* FUNCTION Get the angular damping of the body. **Parameters** - `body` (b2Body) - body **Returns** - `damping` (number) - the damping ### b2d.body.get_angular_velocity *Type:* FUNCTION Get the angular velocity. **Parameters** - `body` (b2Body) - body **Returns** - `velocity` (number) - the angular velocity in radians/second. ### b2d.body.get_angular_velocity *Type:* FUNCTION Get the angular velocity. **Parameters** - `body` (b2Body) - body **Returns** - `velocity` (number) - the angular velocity in radians/second. ### b2d.body.get_gravity_scale *Type:* FUNCTION Get the gravity scale of the body. **Parameters** - `body` (b2Body) - body **Returns** - `scale` (number) - the scale ### b2d.body.get_gravity_scale *Type:* FUNCTION Get the gravity scale of the body. **Parameters** - `body` (b2Body) - body **Returns** - `scale` (number) - the scale ### b2d.body.get_inertia *Type:* FUNCTION Get the rotational inertia of the body about the local origin. **Parameters** - `body` (b2Body) - body **Returns** - `inertia` (number) - the rotational inertia, usually in kg-m^2. ### b2d.body.get_linear_damping *Type:* FUNCTION Get the linear damping of the body. **Parameters** - `body` (b2Body) - body **Returns** - `damping` (number) - the damping ### b2d.body.get_linear_damping *Type:* FUNCTION Get the linear damping of the body. **Parameters** - `body` (b2Body) - body **Returns** - `damping` (number) - the damping ### b2d.body.get_linear_velocity *Type:* FUNCTION Get the linear velocity of the center of mass. **Parameters** - `body` (b2Body) - body **Returns** - `velocity` (vector3) - the linear velocity of the center of mass. ### b2d.body.get_linear_velocity *Type:* FUNCTION Get the linear velocity of the center of mass. **Parameters** - `body` (b2Body) - body **Returns** - `velocity` (vector3) - the linear velocity of the center of mass. ### b2d.body.get_linear_velocity_from_local_point *Type:* FUNCTION Get the world velocity of a local point. **Parameters** - `body` (b2Body) - body - `local_point` (vector3) - a point in local coordinates. **Returns** - `velocity` (vector3) - the world velocity of a point. ### b2d.body.get_linear_velocity_from_local_point *Type:* FUNCTION Get the world velocity of a local point. **Parameters** - `body` (b2Body) - body - `local_point` (vector3) - a point in local coordinates. **Returns** - `velocity` (vector3) - the world velocity of a point. ### b2d.body.get_linear_velocity_from_world_point *Type:* FUNCTION Get the world linear velocity of a world point attached to this body. **Parameters** - `body` (b2Body) - body - `world_point` (vector3) - a point in world coordinates. **Returns** - `velocity` (vector3) - the world velocity of a point. ### b2d.body.get_linear_velocity_from_world_point *Type:* FUNCTION Get the world linear velocity of a world point attached to this body. **Parameters** - `body` (b2Body) - body - `world_point` (vector3) - a point in world coordinates. **Returns** - `velocity` (vector3) - the world velocity of a point. ### b2d.body.get_local_center *Type:* FUNCTION Get the local position of the center of mass. **Parameters** - `body` (b2Body) - body **Returns** - `center` (vector3) - Get the local position of the center of mass. ### b2d.body.get_local_center_of_mass *Type:* FUNCTION Get the local position of the center of mass. **Parameters** - `body` (b2Body) - body **Returns** - `center` (vector3) - Get the local position of the center of mass. ### b2d.body.get_local_point *Type:* FUNCTION Gets a local point relative to the body's origin given a world point. **Parameters** - `body` (b2Body) - body - `world_point` (vector3) - a point in world coordinates. **Returns** - `vector` (vector3) - the corresponding local point relative to the body's origin. ### b2d.body.get_local_point *Type:* FUNCTION Gets a local point relative to the body's origin given a world point. **Parameters** - `body` (b2Body) - body - `world_point` (vector3) - a point in world coordinates. **Returns** - `vector` (vector3) - the corresponding local point relative to the body's origin. ### b2d.body.get_local_vector *Type:* FUNCTION Gets a local vector given a world vector. **Parameters** - `body` (b2Body) - body - `world_vector` (vector3) - a vector in world coordinates. **Returns** - `vector` (vector3) - the corresponding local vector. ### b2d.body.get_local_vector *Type:* FUNCTION Gets a local vector given a world vector. **Parameters** - `body` (b2Body) - body - `world_vector` (vector3) - a vector in world coordinates. **Returns** - `vector` (vector3) - the corresponding local vector. ### b2d.body.get_mass *Type:* FUNCTION Get the total mass of the body. **Parameters** - `body` (b2Body) - body **Returns** - `mass` (number) - the mass, usually in kilograms (kg). ### b2d.body.get_mass *Type:* FUNCTION Get the total mass of the body. **Parameters** - `body` (b2Body) - body **Returns** - `mass` (number) - the mass, usually in kilograms (kg). ### b2d.body.get_next *Type:* FUNCTION Get the next body in the world's body list. **Parameters** - `body` (b2Body) - body **Returns** - `body` (b2Body) - the next body ### b2d.body.get_position *Type:* FUNCTION Get the world body origin position. **Parameters** - `body` (b2Body) - body **Returns** - `position` (vector3) - the world position of the body's origin. ### b2d.body.get_position *Type:* FUNCTION Get the world body origin position. **Parameters** - `body` (b2Body) - body **Returns** - `position` (vector3) - the world position of the body's origin. ### b2d.body.get_rotational_inertia *Type:* FUNCTION Get the rotational inertia of the body about the local origin. **Parameters** - `body` (b2Body) - body **Returns** - `inertia` (number) - the rotational inertia, usually in kg-m^2. ### b2d.body.get_type *Type:* FUNCTION Get the type of this body. **Parameters** - `body` (b2Body) - body **Returns** - `type` (b2BodyType) - the body type ### b2d.body.get_type *Type:* FUNCTION Get the type of this body. **Parameters** - `body` (b2Body) - body **Returns** - `type` (b2BodyType) - the body type ### b2d.body.get_world *Type:* FUNCTION Get the parent world of this body. **Parameters** - `body` (b2Body) - body **Returns** - `world` (b2World) ### b2d.body.get_world *Type:* FUNCTION Get the parent world of this body. **Parameters** - `body` (b2Body) - body **Returns** - `world` (b2World) ### b2d.body.get_world_center *Type:* FUNCTION Get the angle in radians. **Parameters** - `body` (b2Body) - body **Returns** - `angle` (number) - the current world rotation angle in radians. ### b2d.body.get_world_center *Type:* FUNCTION Get the world position of the center of mass. **Parameters** - `body` (b2Body) - body **Returns** - `center` (vector3) - Get the world position of the center of mass. ### b2d.body.get_world_center_of_mass *Type:* FUNCTION Get the world position of the center of mass. **Parameters** - `body` (b2Body) - body **Returns** - `center` (vector3) - Get the world position of the center of mass. ### b2d.body.get_world_point *Type:* FUNCTION Get the world coordinates of a point given the local coordinates. **Parameters** - `body` (b2Body) - body - `local_vector` (vector3) - localPoint a point on the body measured relative the the body's origin. **Returns** - `vector` (vector3) - the same point expressed in world coordinates. ### b2d.body.get_world_point *Type:* FUNCTION Get the world coordinates of a point given the local coordinates. **Parameters** - `body` (b2Body) - body - `local_vector` (vector3) - localPoint a point on the body measured relative the the body's origin. **Returns** - `vector` (vector3) - the same point expressed in world coordinates. ### b2d.body.get_world_vector *Type:* FUNCTION Get the world coordinates of a vector given the local coordinates. **Parameters** - `body` (b2Body) - body - `local_vector` (vector3) - a vector fixed in the body. **Returns** - `vector` (vector3) - the same vector expressed in world coordinates. ### b2d.body.get_world_vector *Type:* FUNCTION Get the world coordinates of a vector given the local coordinates. **Parameters** - `body` (b2Body) - body - `local_vector` (vector3) - a vector fixed in the body. **Returns** - `vector` (vector3) - the same vector expressed in world coordinates. ### b2d.body.is_active *Type:* FUNCTION Get the active state of the body. **Parameters** - `body` (b2Body) - body **Returns** - `enabled` (boolean) - is the body active ### b2d.body.is_active *Type:* FUNCTION Get the active state of the body. **Parameters** - `body` (b2Body) - body **Returns** - `enabled` (boolean) - is the body active ### b2d.body.is_awake *Type:* FUNCTION Get the sleeping state of this body. **Parameters** - `body` (b2Body) - body **Returns** - `enabled` (boolean) - true if the body is awake, false if it's sleeping. ### b2d.body.is_awake *Type:* FUNCTION Get the sleeping state of this body. **Parameters** - `body` (b2Body) - body **Returns** - `enabled` (boolean) - true if the body is awake, false if it's sleeping. ### b2d.body.is_bullet *Type:* FUNCTION Is this body in bullet mode **Parameters** - `body` (b2Body) - body **Returns** - `enabled` (boolean) - true if the body is in bullet mode ### b2d.body.is_bullet *Type:* FUNCTION Is this body in bullet mode **Parameters** - `body` (b2Body) - body **Returns** - `enabled` (boolean) - true if the body is in bullet mode ### b2d.body.is_fixed_rotation *Type:* FUNCTION Does this body have fixed rotation? **Parameters** - `body` (b2Body) - body **Returns** - `enabled` (boolean) - is the rotation fixed ### b2d.body.is_fixed_rotation *Type:* FUNCTION Does this body have fixed rotation? **Parameters** - `body` (b2Body) - body **Returns** - `enabled` (boolean) - is the rotation fixed ### b2d.body.is_sleeping_allowed *Type:* FUNCTION Is this body allowed to sleep **Parameters** - `body` (b2Body) - body **Returns** - `enabled` (boolean) - true if the body is allowed to sleep ### b2d.body.is_sleeping_enabled *Type:* FUNCTION Is this body allowed to sleep **Parameters** - `body` (b2Body) - body **Returns** - `enabled` (boolean) - true if the body is allowed to sleep ### b2d.body.reset_mass_data *Type:* FUNCTION This resets the mass properties to the sum of the mass properties of the fixtures. This normally does not need to be called unless you called SetMassData to override **Parameters** - `body` (b2Body) - body ### b2d.body.reset_mass_data *Type:* FUNCTION This resets the mass properties to the sum of the mass properties of the fixtures. This normally does not need to be called unless you called SetMassData to override **Parameters** - `body` (b2Body) - body ### b2d.body.set_active *Type:* FUNCTION Set the active state of the body. An inactive body is not simulated and cannot be collided with or woken up. If you pass a flag of true, all fixtures will be added to the broad-phase. If you pass a flag of false, all fixtures will be removed from the broad-phase and all contacts will be destroyed. Fixtures and joints are otherwise unaffected. You may continue to create/destroy fixtures and joints on inactive bodies. Fixtures on an inactive body are implicitly inactive and will not participate in collisions, ray-casts, or queries. Joints connected to an inactive body are implicitly inactive. An inactive body is still owned by a b2World object and remains in the body list. **Parameters** - `body` (b2Body) - body - `enable` (boolean) - true if the body should be active ### b2d.body.set_active *Type:* FUNCTION Set the active state of the body. An inactive body is not simulated and cannot be collided with or woken up. If you pass a flag of true, all fixtures will be added to the broad-phase. If you pass a flag of false, all fixtures will be removed from the broad-phase and all contacts will be destroyed. Fixtures and joints are otherwise unaffected. You may continue to create/destroy fixtures and joints on inactive bodies. Fixtures on an inactive body are implicitly inactive and will not participate in collisions, ray-casts, or queries. Joints connected to an inactive body are implicitly inactive. An inactive body is still owned by a b2World object and remains in the body list. **Parameters** - `body` (b2Body) - body - `enable` (boolean) - true if the body should be active ### b2d.body.set_angular_damping *Type:* FUNCTION Set the angular damping of the body. **Parameters** - `body` (b2Body) - body - `damping` (number) - the damping ### b2d.body.set_angular_damping *Type:* FUNCTION Set the angular damping of the body. **Parameters** - `body` (b2Body) - body - `damping` (number) - the damping ### b2d.body.set_angular_velocity *Type:* FUNCTION Set the angular velocity. **Parameters** - `body` (b2Body) - body - `omega` (number) - the new angular velocity in radians/second. ### b2d.body.set_angular_velocity *Type:* FUNCTION Set the angular velocity. **Parameters** - `body` (b2Body) - body - `omega` (number) - the new angular velocity in radians/second. ### b2d.body.set_awake *Type:* FUNCTION Set the sleep state of the body. A sleeping body has very low CPU cost. **Parameters** - `body` (b2Body) - body - `enable` (boolean) - flag set to false to put body to sleep, true to wake it. ### b2d.body.set_awake *Type:* FUNCTION Set the sleep state of the body. A sleeping body has very low CPU cost. **Parameters** - `body` (b2Body) - body - `enable` (boolean) - flag set to false to put body to sleep, true to wake it. ### b2d.body.set_bullet *Type:* FUNCTION Should this body be treated like a bullet for continuous collision detection? **Parameters** - `body` (b2Body) - body - `enable` (boolean) - if true, the body will be in bullet mode ### b2d.body.set_bullet *Type:* FUNCTION Should this body be treated like a bullet for continuous collision detection? **Parameters** - `body` (b2Body) - body - `enable` (boolean) - if true, the body will be in bullet mode ### b2d.body.set_fixed_rotation *Type:* FUNCTION Set this body to have fixed rotation. This causes the mass to be reset. **Parameters** - `body` (b2Body) - body - `enable` (boolean) - true if the rotation should be fixed ### b2d.body.set_fixed_rotation *Type:* FUNCTION Set this body to have fixed rotation. This causes the mass to be reset. **Parameters** - `body` (b2Body) - body - `enable` (boolean) - true if the rotation should be fixed ### b2d.body.set_gravity_scale *Type:* FUNCTION Set the gravity scale of the body. **Parameters** - `body` (b2Body) - body - `scale` (number) - the scale ### b2d.body.set_gravity_scale *Type:* FUNCTION Set the gravity scale of the body. **Parameters** - `body` (b2Body) - body - `scale` (number) - the scale ### b2d.body.set_linear_damping *Type:* FUNCTION Set the linear damping of the body. **Parameters** - `body` (b2Body) - body - `damping` (number) - the damping ### b2d.body.set_linear_damping *Type:* FUNCTION Set the linear damping of the body. **Parameters** - `body` (b2Body) - body - `damping` (number) - the damping ### b2d.body.set_linear_velocity *Type:* FUNCTION Set the linear velocity of the center of mass. **Parameters** - `body` (b2Body) - body - `velocity` (vector3) - the new linear velocity of the center of mass. ### b2d.body.set_linear_velocity *Type:* FUNCTION Set the linear velocity of the center of mass. **Parameters** - `body` (b2Body) - body - `velocity` (vector3) - the new linear velocity of the center of mass. ### b2d.body.set_sleeping_allowed *Type:* FUNCTION You can disable sleeping on this body. If you disable sleeping, the body will be woken. **Parameters** - `body` (b2Body) - body - `enable` (boolean) - if false, the body will never sleep, and consume more CPU ### b2d.body.set_transform *Type:* FUNCTION Set the position of the body's origin and rotation. This breaks any contacts and wakes the other bodies. Manipulating a body's transform may cause non-physical behavior. **Parameters** - `body` (b2Body) - body - `position` (vector3) - the world position of the body's local origin. - `angle` (number) - the world position of the body's local origin. ### b2d.body.set_transform *Type:* FUNCTION Set the position of the body's origin and rotation. This breaks any contacts and wakes the other bodies. Manipulating a body's transform may cause non-physical behavior. **Parameters** - `body` (b2Body) - body - `position` (vector3) - the world position of the body's local origin. - `angle` (number) - the world position of the body's local origin. ### b2d.body.set_type *Type:* FUNCTION Set the type of this body. This may alter the mass and velocity. **Parameters** - `body` (b2Body) - body - `type` (b2BodyType) - the body type ### b2d.body.set_type *Type:* FUNCTION Set the type of this body. This may alter the mass and velocity. **Parameters** - `body` (b2Body) - body - `type` (b2BodyType) - the body type ### b2World *Type:* TYPEDEF Box2D world **Parameters** - `value` (userdata) # Base {#apis:base-lua} **Namespace:** `base` **Language:** Lua **Type:** Defold Lua **File:** `lua_base.doc_h` **Source:** `engine/lua/src/lua_base.doc_h` Documentation for the Lua base standard library. From [Lua 5.1 Reference Manual](https://www.lua.org/manual/5.1/) by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes. Copyright © 2006-2012 Lua.org, PUC-Rio. Freely available under the terms of the [Lua license](https://www.lua.org/license.html). ## API ### _G *Type:* VARIABLE A global variable (not a function) that holds the global environment (that is, _G._G = _G). Lua itself does not use this variable; changing its value does not affect any environment, nor vice-versa. (Use setfenv to change environments.) ### _VERSION *Type:* VARIABLE A global variable (not a function) that holds a string containing the current interpreter version. The current contents of this variable is "Lua 5.1". ### assert *Type:* FUNCTION Issues an error when the value of its argument v is false (i.e., nil or false); otherwise, returns all its arguments. message is an error message; when absent, it defaults to "assertion failed!" **Parameters** - `v` (boolean) - `message` (string) (optional) ### collectgarbage *Type:* FUNCTION This function is a generic interface to the garbage collector. It performs different functions according to its first argument, opt: "collect" performs a full garbage-collection cycle. This is the default option. "stop" stops the garbage collector. "restart" restarts the garbage collector. "count" returns the total memory in use by Lua (in Kbytes). "step" performs a garbage-collection step. The step "size" is controlled by arg (larger values mean more steps) in a non-specified way. If you want to control the step size you must experimentally tune the value of arg. Returns true if the step finished a collection cycle. "setpause" sets arg as the new value for the pause of the collector . Returns the previous value for pause. "setstepmul" sets arg as the new value for the step multiplier of the collector . Returns the previous value for step. **Parameters** - `opt` (table) (optional) - `arg` (number) (optional) ### dofile *Type:* FUNCTION Opens the named file and executes its contents as a Lua chunk. When called without arguments, dofile executes the contents of the standard input (stdin). Returns all values returned by the chunk. In case of errors, dofile propagates the error to its caller (that is, dofile does not run in protected mode). **Parameters** - `filename` (string) (optional) ### error *Type:* FUNCTION Terminates the last protected function called and returns message as the error message. Function error never returns. Usually, error adds some information about the error position at the beginning of the message. The level argument specifies how to get the error position. With level 1 (the default), the error position is where the error function was called. Level 2 points the error to where the function that called error was called; and so on. Passing a level 0 avoids the addition of error position information to the message. **Parameters** - `message` (string) - `level` (number) (optional) ### getfenv *Type:* FUNCTION Returns the current environment in use by the function. f can be a Lua function or a number that specifies the function at that stack level: Level 1 is the function calling getfenv. If the given function is not a Lua function, or if f is 0, getfenv returns the global environment. The default for f is 1. **Parameters** - `f` (function) (optional) ### getmetatable *Type:* FUNCTION If object does not have a metatable, returns nil. Otherwise, if the object's metatable has a "__metatable" field, returns the associated value. Otherwise, returns the metatable of the given object. **Parameters** - `object` (table) ### ipairs *Type:* FUNCTION Returns three values: an iterator function, the table t, and 0, so that the construction ``` for i,v in ipairs(t) do body end ``` will iterate over the pairs (1,t[1]), (2,t[2]), ..., up to the first integer key absent from the table. **Parameters** - `t` (table) ### load *Type:* FUNCTION Loads a chunk using function func to get its pieces. Each call to func must return a string that concatenates with previous results. A return of an empty string, nil, or no value signals the end of the chunk. If there are no errors, returns the compiled chunk as a function; otherwise, returns nil plus the error message. The environment of the returned function is the global environment. chunkname is used as the chunk name for error messages and debug information. When absent, it defaults to "=(load)". **Parameters** - `func` (function) - `chunkname` (string) (optional) ### loadfile *Type:* FUNCTION Similar to load, but gets the chunk from file filename or from the standard input, if no file name is given. **Parameters** - `filename` (string) (optional) ### loadstring *Type:* FUNCTION Similar to load, but gets the chunk from the given string. To load and run a given string, use the idiom ``` assert(loadstring(s))() ``` When absent, chunkname defaults to the given string. **Parameters** - `string` (string) - `chunkname` (string) (optional) ### module *Type:* FUNCTION Creates a module. If there is a table in package.loaded[name], this table is the module. Otherwise, if there is a global table t with the given name, this table is the module. Otherwise creates a new table t and sets it as the value of the global name and the value of package.loaded[name]. This function also initializes t._NAME with the given name, t._M with the module (t itself), and t._PACKAGE with the package name (the full module name minus last component; see below). Finally, module sets t as the new environment of the current function and the new value of package.loaded[name], so that require returns t. If name is a compound name (that is, one with components separated by dots), module creates (or reuses, if they already exist) tables for each component. For instance, if name is a.b.c, then module stores the module table in field c of field b of global a. This function can receive optional options after the module name, where each option is a function to be applied over the module. **Parameters** - `name` (string) - `...` (...) (optional) ### next *Type:* FUNCTION Allows a program to traverse all fields of a table. Its first argument is a table and its second argument is an index in this table. next returns the next index of the table and its associated value. When called with nil as its second argument, next returns an initial index and its associated value. When called with the last index, or with nil in an empty table, next returns nil. If the second argument is absent, then it is interpreted as nil. In particular, you can use next(t) to check whether a table is empty. The order in which the indices are enumerated is not specified, even for numeric indices. (To traverse a table in numeric order, use a numerical for or the ipairs function.) The behavior of next is undefined if, during the traversal, you assign any value to a non-existent field in the table. You may however modify existing fields. In particular, you may clear existing fields. **Parameters** - `table` (table) - `index` (number) (optional) ### pairs *Type:* FUNCTION Returns three values: the next function, the table t, and nil, so that the construction ``` for k,v in pairs(t) do body end ``` will iterate over all key-{}value pairs of table t. See function next for the caveats of modifying the table during its traversal. **Parameters** - `t` (string) ### pcall *Type:* FUNCTION Calls function f with the given arguments in protected mode. This means that any error inside f is not propagated; instead, pcall catches the error and returns a status code. Its first result is the status code (a boolean), which is true if the call succeeds without errors. In such case, pcall also returns all results from the call, after this first result. In case of any error, pcall returns false plus the error message. **Parameters** - `f` (function) - `arg1` (any) - `...` (...) ### print *Type:* FUNCTION Receives any number of arguments, and prints their values to stdout, using the tostring function to convert them to strings. print is not intended for formatted output, but only as a quick way to show a value, typically for debugging. For formatted output, use string.format. **Parameters** - `...` (...) ### rawequal *Type:* FUNCTION Checks whether v1 is equal to v2, without invoking any metamethod. Returns a boolean. **Parameters** - `v1` (any) - `v2` (any) ### rawget *Type:* FUNCTION Gets the real value of table[index], without invoking any metamethod. table must be a table; index may be any value. **Parameters** - `table` (table) - `index` (number) ### rawset *Type:* FUNCTION Sets the real value of table[index] to value, without invoking any metamethod. table must be a table, index any value different from nil, and value any Lua value. This function returns table. **Parameters** - `table` (table) - `index` (number) - `value` (any) ### require *Type:* FUNCTION Loads the given module. The function starts by looking into the package.loaded table to determine whether modname is already loaded. If it is, then require returns the value stored at package.loaded[modname]. Otherwise, it tries to find a loader for the module. To find a loader, require is guided by the package.loaders array. By changing this array, we can change how require looks for a module. The following explanation is based on the default configuration for package.loaders. First require queries package.preload[modname]. If it has a value, this value (which should be a function) is the loader. Otherwise require searches for a Lua loader using the path stored in package.path. If that also fails, it searches for a C loader using the path stored in package.cpath. If that also fails, it tries an all-in-one loader . Once a loader is found, require calls the loader with a single argument, modname. If the loader returns any value, require assigns the returned value to package.loaded[modname]. If the loader returns no value and has not assigned any value to package.loaded[modname], then require assigns true to this entry. In any case, require returns the final value of package.loaded[modname]. If there is any error loading or running the module, or if it cannot find any loader for the module, then require signals an error. **Parameters** - `modname` (string) ### select *Type:* FUNCTION If index is a number, returns all arguments after argument number index. Otherwise, index must be the string "#", and select returns the total number of extra arguments it received. **Parameters** - `index` (number) - `...` (...) ### setfenv *Type:* FUNCTION Sets the environment to be used by the given function. f can be a Lua function or a number that specifies the function at that stack level: Level 1 is the function calling setfenv. setfenv returns the given function. As a special case, when f is 0 setfenv changes the environment of the running thread. In this case, setfenv returns no values. **Parameters** - `f` (function) - `table` (table) ### setmetatable *Type:* FUNCTION Sets the metatable for the given table. (You cannot change the metatable of other types from Lua, only from C.) If metatable is nil, removes the metatable of the given table. If the original metatable has a "__metatable" field, raises an error. This function returns table. **Parameters** - `table` (table) - `metatable` (table) ### tonumber *Type:* FUNCTION Tries to convert its argument to a number. If the argument is already a number or a string convertible to a number, then tonumber returns this number; otherwise, it returns nil. An optional argument specifies the base to interpret the numeral. The base may be any integer between 2 and 36, inclusive. In bases above 10, the letter 'A' (in either upper or lower case) represents 10, 'B' represents 11, and so forth, with 'Z' representing 35. In base 10 (the default), the number can have a decimal part, as well as an optional exponent part . In other bases, only unsigned integers are accepted. **Parameters** - `e` (string) - `base` (number) (optional) ### tostring *Type:* FUNCTION Receives an argument of any type and converts it to a string in a reasonable format. For complete control of how numbers are converted, use string.format. If the metatable of e has a "__tostring" field, then tostring calls the corresponding value with e as argument, and uses the result of the call as its result. **Parameters** - `e` (any) ### type *Type:* FUNCTION Returns the type of its only argument, coded as a string. The possible results of this function are "nil" (a string, not the value nil), "number", "string", "boolean", "table", "function", "thread", and "userdata". **Parameters** - `v` (any) ### unpack *Type:* FUNCTION Returns the elements from the given table. This function is equivalent to ``` return list[i], list[i+1], ..., list[j] ``` except that the above code can be written only for a fixed number of elements. By default, i is 1 and j is the length of the list, as defined by the length operator . **Parameters** - `list` (table) - `i` (number) (optional) - `j` (number) (optional) ### xpcall *Type:* FUNCTION This function is similar to pcall, except that you can set a new error handler. xpcall calls function f in protected mode, using err as the error handler. Any error inside f is not propagated; instead, xpcall catches the error, calls the err function with the original error object, and returns a status code. Its first result is the status code (a boolean), which is true if the call succeeds without errors. In this case, xpcall also returns all results from the call, after this first result. In case of any error, xpcall returns false plus the result from err. **Parameters** - `f` (function) - `err` (string) # BitOp {#apis:bit-lua} **Namespace:** `bit` **Language:** Lua **Type:** Defold Lua **File:** `script_bitop.cpp` **Source:** `engine/script/src/script_bitop.cpp` [Lua BitOp](http://bitop.luajit.org/api.html) is a C extension module for Lua 5.1/5.2 which adds bitwise operations on numbers. Lua BitOp is Copyright © 2008-2012 Mike Pall. Lua BitOp is free software, released under the MIT license (same license as the Lua core). Lua BitOp is compatible with the built-in bitwise operations in LuaJIT 2.0 and is used on platforms where Defold runs without LuaJIT. For clarity the examples assume the definition of a helper function `printx()`. This prints its argument as an unsigned 32 bit hexadecimal number on all platforms: ```lua function printx(x) print("0x"..bit.tohex(x)) end ``` ## API ### bit.arshift *Type:* FUNCTION Returns the bitwise arithmetic right-shift of its first argument by the number of bits given by the second argument. Arithmetic right-shift treats the most-significant bit as a sign bit and replicates it. Only the lower 5 bits of the shift count are used (reduces to the range [0..31]). **Parameters** - `x` (number) - number - `n` (number) - number of bits **Returns** - `y` (number) - bitwise arithmetic right-shifted number **Examples** ``` print(bit.arshift(256, 8)) --> 1 print(bit.arshift(-256, 8)) --> -1 printx(bit.arshift(0x87654321, 12)) --> 0xfff87654 ``` ### bit.band *Type:* FUNCTION Returns the bitwise and of all of its arguments. Note that more than two arguments are allowed. **Parameters** - `x1` (number) - number - `x2...` (number) (optional) - number(s) **Returns** - `y` (number) - bitwise and of the provided arguments **Examples** ``` printx(bit.band(0x12345678, 0xff)) --> 0x00000078 ``` ### bit.bnot *Type:* FUNCTION Returns the bitwise not of its argument. **Parameters** - `x` (number) - number **Returns** - `y` (number) - bitwise not of number x **Examples** ``` print(bit.bnot(0)) --> -1 printx(bit.bnot(0)) --> 0xffffffff print(bit.bnot(-1)) --> 0 print(bit.bnot(0xffffffff)) --> 0 printx(bit.bnot(0x12345678)) --> 0xedcba987 ``` ### bit.bor *Type:* FUNCTION Returns the bitwise or of all of its arguments. Note that more than two arguments are allowed. **Parameters** - `x1` (number) - number - `x2...` (number) (optional) - number(s) **Returns** - `y` (number) - bitwise or of the provided arguments **Examples** ``` print(bit.bor(1, 2, 4, 8)) --> 15 ``` ### bit.bswap *Type:* FUNCTION Swaps the bytes of its argument and returns it. This can be used to convert little-endian 32 bit numbers to big-endian 32 bit numbers or vice versa. **Parameters** - `x` (number) - number **Returns** - `y` (number) - bitwise swapped number **Examples** ``` printx(bit.bswap(0x12345678)) --> 0x78563412 printx(bit.bswap(0x78563412)) --> 0x12345678 ``` ### bit.bxor *Type:* FUNCTION Returns the bitwise xor of all of its arguments. Note that more than two arguments are allowed. **Parameters** - `x1` (number) - number - `x2...` (number) (optional) - number(s) **Returns** - `y` (number) - bitwise xor of the provided arguments **Examples** ``` printx(bit.bxor(0xa5a5f0f0, 0xaa55ff00)) --> 0x0ff00ff0 ``` ### bit.lshift *Type:* FUNCTION Returns the bitwise logical left-shift of its first argument by the number of bits given by the second argument. Logical shifts treat the first argument as an unsigned number and shift in 0-bits. Only the lower 5 bits of the shift count are used (reduces to the range [0..31]). **Parameters** - `x` (number) - number - `n` (number) - number of bits **Returns** - `y` (number) - bitwise logical left-shifted number **Examples** ``` print(bit.lshift(1, 0)) --> 1 print(bit.lshift(1, 8)) --> 256 print(bit.lshift(1, 40)) --> 256 printx(bit.lshift(0x87654321, 12)) --> 0x54321000 ``` ### bit.rol *Type:* FUNCTION Returns the bitwise left rotation of its first argument by the number of bits given by the second argument. Bits shifted out on one side are shifted back in on the other side. Only the lower 5 bits of the rotate count are used (reduces to the range [0..31]). **Parameters** - `x` (number) - number - `n` (number) - number of bits **Returns** - `y` (number) - bitwise left-rotated number **Examples** ``` printx(bit.rol(0x12345678, 12)) --> 0x45678123 ``` ### bit.ror *Type:* FUNCTION Returns the bitwise right rotation of its first argument by the number of bits given by the second argument. Bits shifted out on one side are shifted back in on the other side. Only the lower 5 bits of the rotate count are used (reduces to the range [0..31]). **Parameters** - `x` (number) - number - `n` (number) - number of bits **Returns** - `y` (number) - bitwise right-rotated number **Examples** ``` printx(bit.ror(0x12345678, 12)) --> 0x67812345 ``` ### bit.rshift *Type:* FUNCTION Returns the bitwise logical right-shift of its first argument by the number of bits given by the second argument. Logical shifts treat the first argument as an unsigned number and shift in 0-bits. Only the lower 5 bits of the shift count are used (reduces to the range [0..31]). **Parameters** - `x` (number) - number - `n` (number) - number of bits **Returns** - `y` (number) - bitwise logical right-shifted number **Examples** ``` print(bit.rshift(256, 8)) --> 1 print(bit.rshift(-256, 8)) --> 16777215 printx(bit.rshift(0x87654321, 12)) --> 0x00087654 ``` ### bit.tobit *Type:* FUNCTION Normalizes a number to the numeric range for bit operations and returns it. This function is usually not needed since all bit operations already normalize all of their input arguments. **Parameters** - `x` (number) - number to normalize **Returns** - `y` (number) - normalized number **Examples** ``` print(0xffffffff) --> 4294967295 (*) print(bit.tobit(0xffffffff)) --> -1 printx(bit.tobit(0xffffffff)) --> 0xffffffff print(bit.tobit(0xffffffff + 1)) --> 0 print(bit.tobit(2^40 + 1234)) --> 1234 ``` (*) See the treatment of hex literals for an explanation why the printed numbers in the first two lines differ (if your Lua installation uses a double number type). ### bit.tohex *Type:* FUNCTION Converts its first argument to a hex string. The number of hex digits is given by the absolute value of the optional second argument. Positive numbers between 1 and 8 generate lowercase hex digits. Negative numbers generate uppercase hex digits. Only the least-significant 4*|n| bits are used. The default is to generate 8 lowercase hex digits. **Parameters** - `x` (number) - number to convert - `n` (number) - number of hex digits to return **Returns** - `s` (string) - hexadecimal string **Examples** ``` print(bit.tohex(1)) --> 00000001 print(bit.tohex(-1)) --> ffffffff print(bit.tohex(0xffffffff)) --> ffffffff print(bit.tohex(-1, -8)) --> FFFFFFFF print(bit.tohex(0x21, 4)) --> 0021 print(bit.tohex(0x87654321, 4)) --> 4321 ``` # Buffer {#apis:buffer-lua} **Namespace:** `buffer` **Language:** Lua **Type:** Defold Lua **File:** `script_buffer.cpp` **Source:** `engine/gamesys/src/gamesys/scripts/script_buffer.cpp` Functions for manipulating buffers and streams ## API ### buffer.copy_buffer *Type:* FUNCTION Copy all data streams from one buffer to another, element wise. Each of the source streams must have a matching stream in the destination buffer. The streams must match in both type and size. The source and destination buffer can be the same. **Parameters** - `dst` (buffer) - the destination buffer - `dstoffset` (number) - the offset to start copying data to - `src` (buffer) - the source data buffer - `srcoffset` (number) - the offset to start copying data from - `count` (number) - the number of elements to copy **Examples** How to copy elements (e.g. vertices) from one buffer to another ``` -- copy entire buffer buffer.copy_buffer(dstbuffer, 0, srcbuffer, 0, #srcbuffer) -- copy last 10 elements to the front of another buffer buffer.copy_buffer(dstbuffer, 0, srcbuffer, #srcbuffer - 10, 10) ``` ### buffer.copy_stream *Type:* FUNCTION Copy a specified amount of data from one stream to another. The value type and size must match between source and destination streams. The source and destination streams can be the same. **Parameters** - `dst` (bufferstream) - the destination stream - `dstoffset` (number) - the offset to start copying data to (measured in value type) - `src` (bufferstream) - the source data stream - `srcoffset` (number) - the offset to start copying data from (measured in value type) - `count` (number) - the number of values to copy (measured in value type) **Examples** How to update a texture of a sprite: ``` -- copy entire stream local srcstream = buffer.get_stream(srcbuffer, hash("xyz")) local dststream = buffer.get_stream(dstbuffer, hash("xyz")) buffer.copy_stream(dststream, 0, srcstream, 0, #srcstream) ``` ### buffer.create *Type:* FUNCTION Create a new data buffer containing a specified set of streams. A data buffer can contain one or more streams with typed data. This is useful for managing compound data, for instance a vertex buffer could contain separate streams for vertex position, color, normal etc. **Parameters** - `element_count` (number) - The number of elements the buffer should hold - `declaration` (table) - A table where each entry (table) describes a stream
  • hash | string name: The name of the stream
  • constant type: The data type of the stream
  • number count: The number of values each element should hold
**Returns** - `buffer` (buffer) - the new buffer **Examples** How to create and initialize a buffer ``` function init(self) local size = 128 self.image = buffer.create( size * size, { {name=hash("rgb"), type=buffer.VALUE_TYPE_UINT8, count=3 } }) self.imagestream = buffer.get_stream(self.image, hash("rgb")) for y=0,self.height-1 do for x=0,self.width-1 do local index = y * self.width * 3 + x * 3 + 1 self.imagestream[index + 0] = self.r self.imagestream[index + 1] = self.g self.imagestream[index + 2] = self.b end end ``` ### buffer.get_bytes *Type:* FUNCTION Get a copy of all the bytes from a specified stream as a Lua string. **Parameters** - `buffer` (buffer) - the source buffer - `stream_name` (hash) - the name of the stream **Returns** - `data` (string) - the buffer data as a Lua string ### buffer.get_metadata *Type:* FUNCTION Get a named metadata entry from a buffer along with its type. **Parameters** - `buf` (buffer) - the buffer to get the metadata from - `metadata_name` (hash | string) - name of the metadata entry **Returns** - `values` (table | nil) - table of metadata values or nil if the entry does not exist - `value_type` (constant | nil) - numeric type of values or nil **Examples** How to get a metadata entry from a buffer ``` -- retrieve a metadata entry named "somefloats" and its nomeric type local values, type = buffer.get_metadata(buf, hash("somefloats")) if metadata then print(#metadata.." values in 'somefloats'") end ``` ### buffer.get_stream *Type:* FUNCTION Get a specified stream from a buffer. **Parameters** - `buffer` (buffer) - the buffer to get the stream from - `stream_name` (hash | string) - the stream name **Returns** - `stream` (bufferstream) - the data stream ### buffer.set_metadata *Type:* FUNCTION Creates or updates a metadata array entry on a buffer. The value type and count given when updating the entry should match those used when first creating it. **Parameters** - `buf` (buffer) - the buffer to set the metadata on - `metadata_name` (hash | string) - name of the metadata entry - `values` (table) - actual metadata, an array of numeric values - `value_type` (constant) - type of values when stored **Examples** How to set a metadata entry on a buffer ``` -- create a new metadata entry with three floats buffer.set_metadata(buf, hash("somefloats"), {1.5, 3.2, 7.9}, buffer.VALUE_TYPE_FLOAT32) -- ... -- update to a new set of values buffer.set_metadata(buf, hash("somefloats"), {-2.5, 10.0, 32.2}, buffer.VALUE_TYPE_FLOAT32) ``` ### buffer.VALUE_TYPE_FLOAT32 *Type:* CONSTANT Float, single precision, 4 bytes ### buffer.VALUE_TYPE_INT16 *Type:* CONSTANT Signed integer, 2 bytes ### buffer.VALUE_TYPE_INT32 *Type:* CONSTANT Signed integer, 4 bytes ### buffer.VALUE_TYPE_INT64 *Type:* CONSTANT Signed integer, 8 bytes ### buffer.VALUE_TYPE_INT8 *Type:* CONSTANT Signed integer, 1 byte ### buffer.VALUE_TYPE_UINT16 *Type:* CONSTANT Unsigned integer, 2 bytes ### buffer.VALUE_TYPE_UINT32 *Type:* CONSTANT Unsigned integer, 4 bytes ### buffer.VALUE_TYPE_UINT64 *Type:* CONSTANT Unsigned integer, 8 bytes ### buffer.VALUE_TYPE_UINT8 *Type:* CONSTANT Unsigned integer, 1 byte # Built-ins {#apis:builtins-lua} **Namespace:** `builtins` **Language:** Lua **Type:** Defold Lua **File:** `script.cpp` **Source:** `engine/script/src/script.cpp` Built-in scripting functions. ## API ### hash *Type:* FUNCTION All ids in the engine are represented as hashes, so a string needs to be hashed before it can be compared with an id. **Parameters** - `s` (string) - string to hash **Returns** - `hash` (hash) - a hashed string **Examples** To compare a message_id in an on-message callback function: ``` function on_message(self, message_id, message, sender) if message_id == hash("my_message") then -- Act on the message here end end ``` ### hash_to_hex *Type:* FUNCTION Returns a hexadecimal representation of a hash value. The returned string is always padded with leading zeros. **Parameters** - `h` (hash) - hash value to get hex string for **Returns** - `hex` (string) - hex representation of the hash **Examples** ``` local h = hash("my_hash") local hexstr = hash_to_hex(h) print(hexstr) --> a2bc06d97f580aab ``` ### pprint *Type:* FUNCTION Pretty printing of Lua values. This function prints Lua values in a manner similar to +print()+, but will also recurse into tables and pretty print them. There is a limit to how deep the function will recurse. **Parameters** - `v` (any) - value to print **Examples** Pretty printing a Lua table with a nested table: ``` local t2 = { 1, 2, 3, 4 } local t = { key = "value", key2 = 1234, key3 = t2 } pprint(t) ``` Resulting in the following output (note that the key order in non array Lua tables is undefined): ``` { key3 = { 1 = 1, 2 = 2, 3 = 3, 4 = 4, } key2 = 1234, key = value, } ``` # Camera {#apis:camera-lua} **Namespace:** `camera` **Language:** Lua **Type:** Defold Lua **File:** `camera_ddf.proto` **Source:** `engine/gamesys/proto/gamesys/camera_ddf.proto` Messages to control camera components and camera focus. ## API ### aspect_ratio *Type:* PROPERTY The ratio between the frustum width and height. Used when calculating the projection of a perspective camera. The type of the property is number. **Examples** ``` function init(self) local aspect_ratio = go.get("#camera", "aspect_ratio") go.set("#camera", "aspect_ratio", 1.2) end ``` ### camera.get_aspect_ratio *Type:* FUNCTION Gets the effective aspect ratio of the camera. If auto aspect ratio is enabled, returns the aspect ratio calculated from the current render target dimensions. Otherwise returns the manually set aspect ratio. **Parameters** - `camera` (url | number | nil) - camera id **Returns** - `aspect_ratio` (number) - the effective aspect ratio. ### camera.get_auto_aspect_ratio *Type:* FUNCTION Returns whether auto aspect ratio is enabled. When enabled, the camera automatically calculates aspect ratio from render target dimensions. When disabled, uses the manually set aspect ratio value. **Parameters** - `camera` (url | number | nil) - camera id **Returns** - `auto_aspect_ratio` (boolean) - true if auto aspect ratio is enabled ### camera.get_cameras *Type:* FUNCTION This function returns a table with all the camera URLs that have been registered in the render context. **Returns** - `cameras` (table) - a table with all camera URLs **Examples** ``` for k,v in pairs(camera.get_cameras()) do render.set_camera(v) render.draw(...) render.set_camera() end ``` ### camera.get_enabled *Type:* FUNCTION get enabled **Parameters** - `camera` (url | number | nil) - camera id **Returns** - `flag` (boolean) - true if the camera is enabled ### camera.get_far_z *Type:* FUNCTION get far z **Parameters** - `camera` (url | number | nil) - camera id **Returns** - `far_z` (number) - the far z. ### camera.get_fov *Type:* FUNCTION get field of view **Parameters** - `camera` (url | number | nil) - camera id **Returns** - `fov` (number) - the field of view. ### camera.get_near_z *Type:* FUNCTION get near z **Parameters** - `camera` (url | number | nil) - camera id **Returns** - `near_z` (number) - the near z. ### camera.get_orthographic_mode *Type:* FUNCTION get orthographic zoom mode **Parameters** - `camera` (url | number | nil) - camera id **Returns** - `mode` (number) - one of camera.ORTHO_MODE_FIXED, camera.ORTHO_MODE_AUTO_FIT or camera.ORTHO_MODE_AUTO_COVER ### camera.get_orthographic_zoom *Type:* FUNCTION get orthographic zoom **Parameters** - `camera` (url | number | nil) - camera id **Returns** - `orthographic_zoom` (number) - the zoom level when the camera uses orthographic projection. ### camera.get_projection *Type:* FUNCTION get projection matrix **Parameters** - `camera` (url | number | nil) - camera id **Returns** - `projection` (matrix4) - the projection matrix. ### camera.get_view *Type:* FUNCTION get view matrix **Parameters** - `camera` (url | number | nil) - camera id **Returns** - `view` (matrix4) - the view matrix. ### camera.ORTHO_MODE_AUTO_COVER *Type:* CONSTANT Computes zoom so the original display area covers the entire window while preserving aspect ratio. Equivalent to using max(window_width/width, window_height/height). ### camera.ORTHO_MODE_AUTO_FIT *Type:* CONSTANT Computes zoom so the original display area (game.project width/height) fits inside the window while preserving aspect ratio. Equivalent to using min(window_width/width, window_height/height). ### camera.ORTHO_MODE_FIXED *Type:* CONSTANT Uses the manually set orthographic zoom value (camera.set_orthographic_zoom). ### camera.screen_to_world *Type:* FUNCTION Converts a screen-space 2D point with view depth to a 3D world point. z is the view depth in world units measured from the camera plane along the camera forward axis. If a camera isn't specified, the last enabled camera is used. **Parameters** - `pos` (vector3) - Screen-space position (x, y) with z as view depth in world units - `camera` (url | number | nil) (optional) - optional camera id **Returns** - `world_pos` (vector3) - the world coordinate **Examples** Place objects at the touch point with a random Z position, keeping them within the visible view zone. ``` function on_input(self, action_id, action) if action_id == hash("touch") then if action.pressed then local percpective_camera = msg.url("#perspective_camera") local random_z = math.random(camera.get_near_z(percpective_camera) + 0.01, camera.get_far_z(percpective_camera) - 0.01) local world_position = camera.screen_to_world(vmath.vector3(action.screen_x, action.screen_y, random_z), percpective_camera) go.set_position(world_position, "/go1") end end end ``` ### camera.screen_xy_to_world *Type:* FUNCTION Converts 2D screen coordinates (x,y) to the 3D world-space point on the camera's near plane for that pixel. If a camera isn't specified, the last enabled camera is used. **Parameters** - `x` (number) - X coordinate on screen. - `y` (number) - Y coordinate on screen. - `camera` (url | number | nil) (optional) - optional camera id **Returns** - `world_pos` (vector3) - the world coordinate on the camera near plane **Examples** Place objects at the touch point. ``` function on_input(self, action_id, action) if action_id == hash("touch") then if action.pressed then local world_position = camera.screen_xy_to_world(action.screen_x, action.screen_y) go.set_position(world_position, "/go1") end end end ``` ### camera.set_aspect_ratio *Type:* FUNCTION Sets the manual aspect ratio for the camera. This value is only used when auto aspect ratio is disabled. To disable auto aspect ratio and use this manual value, call camera.set_auto_aspect_ratio(camera, false). **Parameters** - `camera` (url | number | nil) - camera id - `aspect_ratio` (number) - the manual aspect ratio value. ### camera.set_auto_aspect_ratio *Type:* FUNCTION Enables or disables automatic aspect ratio calculation. When enabled (true), the camera automatically calculates aspect ratio from render target dimensions. When disabled (false), uses the manually set aspect ratio value. **Parameters** - `camera` (url | number | nil) - camera id - `auto_aspect_ratio` (boolean) - true to enable auto aspect ratio ### camera.set_far_z *Type:* FUNCTION set far z **Parameters** - `camera` (url | number | nil) - camera id - `far_z` (number) - the far z. ### camera.set_fov *Type:* FUNCTION set field of view **Parameters** - `camera` (url | number | nil) - camera id - `fov` (number) - the field of view. ### camera.set_near_z *Type:* FUNCTION set near z **Parameters** - `camera` (url | number | nil) - camera id - `near_z` (number) - the near z. ### camera.set_orthographic_mode *Type:* FUNCTION set orthographic zoom mode **Parameters** - `camera` (url | number | nil) - camera id - `mode` (number) - camera.ORTHO_MODE_FIXED, camera.ORTHO_MODE_AUTO_FIT or camera.ORTHO_MODE_AUTO_COVER ### camera.set_orthographic_zoom *Type:* FUNCTION set orthographic zoom **Parameters** - `camera` (url | number | nil) - camera id - `orthographic_zoom` (number) - the zoom level when the camera uses orthographic projection. ### camera.world_to_screen *Type:* FUNCTION Converts a 3D world position to screen-space coordinates with view depth. Returns a vector3 where x and y are in screen pixels and z is the view depth in world units measured from the camera plane along the camera forward axis. The returned z can be used with camera.screen_to_world to reconstruct the world position on the same pixel ray. If a camera isn't specified, the last enabled camera is used. **Parameters** - `world_pos` (vector3) - World-space position - `camera` (url | number | nil) (optional) - optional camera id **Returns** - `screen_pos` (vector3) - Screen position (x,y in pixels, z is view depth) **Examples** Convert go position into screen pisition ``` go.update_world_transform("/go1") local world_pos = go.get_world_position("/go1") local screen_pos = camera.world_to_screen(world_pos) ``` ### far_z *Type:* PROPERTY Camera frustum far plane. The type of the property is float. **Examples** ``` function init(self) local far_z = go.get("#camera", "far_z") go.set("#camera", "far_z", 10) end ``` ### fov *Type:* PROPERTY Vertical field of view of the camera. The type of the property is float. **Examples** ``` function init(self) local fov = go.get("#camera", "fov") go.set("#camera", "fov", fov + 0.1) go.animate("#camera", "fov", go.PLAYBACK_ONCE_PINGPONG, 1.2, go.EASING_LINEAR, 1) end ``` ### near_z *Type:* PROPERTY Camera frustum near plane. The type of the property is float. **Examples** ``` function init(self) local near_z = go.get("#camera", "near_z") go.set("#camera", "near_z", 10) end ``` ### orthographic_zoom *Type:* PROPERTY Zoom level when using an orthographic projection. The type of the property is float. **Examples** ``` function init(self) local orthographic_zoom = go.get("#camera", "orthographic_zoom") go.set("#camera", "orthographic_zoom", 2.0) go.animate("#camera", "orthographic_zoom", go.PLAYBACK_ONCE_PINGPONG, 0.5, go.EASING_INOUTQUAD, 2) end ``` ### projection *Type:* PROPERTY READ ONLY The calculated projection matrix of the camera. The type of the property is matrix4. **Examples** ``` function init(self) local projection = go.get("#camera", "projection") end ``` ### set_camera *Type:* MESSAGE Post this message to a camera-component to set its properties at run-time. **Parameters** - `aspect_ratio` (number) - aspect ratio of the screen (width divided by height) - `fov` (number) - field of view of the lens, measured as the angle in radians between the right and left edge - `near_z` (number) - position of the near clipping plane (distance from camera along relative z) - `far_z` (number) - position of the far clipping plane (distance from camera along relative z) - `orthographic_projection` (boolean) - set to use an orthographic projection - `orthographic_zoom` (number) - zoom level when the camera is using an orthographic projection - `orthographic_mode` (number) - orthographic zoom behavior when orthographic_projection is enabled **Examples** In the examples, it is assumed that the instance of the script has a camera-component with id "camera". ``` msg.post("#camera", "set_camera", {aspect_ratio = 16/9, fov = math.pi * 0.5, near_z = 0.1, far_z = 500}) ``` ### view *Type:* PROPERTY READ ONLY The calculated view matrix of the camera. The type of the property is matrix4. **Examples** ``` function init(self) local view = go.get("#camera", "view") end ``` # Collection factory {#apis:collectionfactory-lua} **Namespace:** `collectionfactory` **Language:** Lua **Type:** Defold Lua **File:** `script_collection_factory.cpp` **Source:** `engine/gamesys/src/gamesys/scripts/script_collection_factory.cpp` Functions for controlling collection factory components which are used to dynamically spawn collections into the runtime. ## API ### collectionfactory.create *Type:* FUNCTION The URL identifies the collectionfactory component that should do the spawning. Spawning is instant, but spawned game objects get their first update calls the following frame. The supplied parameters for position, rotation and scale will be applied to the whole collection when spawned. Script properties in the created game objects can be overridden through a properties-parameter table. The table should contain game object ids (hash) as keys and property tables as values to be used when initiating each spawned game object. See go.property for more information on script properties. The function returns a table that contains a key for each game object id (hash), as addressed if the collection file was top level, and the corresponding spawned instance id (hash) as value with a unique path prefix added to each instance. Calling collectionfactory.create create on a collection factory that is marked as dynamic without having loaded resources using collectionfactory.load will synchronously load and create resources which may affect application performance. **Parameters** - `url` (string | hash | url) - the collection factory component to be used - `position` (vector3) (optional) - position to assign to the newly spawned collection - `rotation` (quaternion) (optional) - rotation to assign to the newly spawned collection - `properties` (table) (optional) - table of script properties to propagate to any new game object instances - `scale` (number | vector3) (optional) - uniform scaling to apply to the newly spawned collection (must be greater than 0). **Returns** - `ids` (table) - a table mapping the id:s from the collection to the new instance id:s **Examples** How to spawn a collection of game objects: ``` function init(self) -- Spawn a small group of enemies. local pos = vmath.vector3(100, 12.5, 0) local rot = vmath.quat_rotation_z(math.pi / 2) local scale = 0.5 local props = {} props[hash("/enemy_leader")] = { health = 1000.0 } props[hash("/enemy_1")] = { health = 200.0 } props[hash("/enemy_2")] = { health = 400.0, color = hash("green") } local self.enemy_ids = collectionfactory.create("#enemyfactory", pos, rot, props, scale) -- enemy_ids now map to the spawned instance ids: -- -- pprint(self.enemy_ids) -- -- DEBUG:SCRIPT: -- { -- hash: [/enemy_leader] = hash: [/collection0/enemy_leader], -- hash: [/enemy_1] = hash: [/collection0/enemy_1], -- hash: [/enemy_2] = hash: [/collection0/enemy_2] -- } -- Send "attack" message to the leader. First look up its instance id. local leader_id = self.enemy_ids[hash("/enemy_leader")] msg.post(leader_id, "attack") end ``` How to delete a spawned collection: ``` go.delete(self.enemy_ids) ``` ### collectionfactory.get_status *Type:* FUNCTION This returns status of the collection factory. Calling this function when the factory is not marked as dynamic loading always returns COMP_COLLECTION_FACTORY_STATUS_LOADED. **Parameters** - `url` (string | hash | url) (optional) - the collection factory component to get status from **Returns** - `status` (constant) - status of the collection factory component
  • collectionfactory.STATUS_UNLOADED
  • collectionfactory.STATUS_LOADING
  • collectionfactory.STATUS_LOADED
### collectionfactory.load *Type:* FUNCTION Resources loaded are referenced by the collection factory component until the existing (parent) collection is destroyed or collectionfactory.unload is called. Calling this function when the factory is not marked as dynamic loading does nothing. **Parameters** - `url` (string | hash | url) (optional) - the collection factory component to load - `complete_function` (function(self, url, result)) (optional) - function to call when resources are loaded.
self
object The current object.
url
url url of the collection factory component
result
boolean True if resource were loaded successfully
**Examples** How to load resources of a collection factory prototype. ``` collectionfactory.load("#factory", function(self, url, result) end) ``` ### collectionfactory.set_prototype *Type:* FUNCTION Changes the prototype for the collection factory. Setting the prototype to "nil" will revert back to the original prototype. **Notes** - - Requires the factory to have the "Dynamic Prototype" set - Cannot be set when the state is COMP_FACTORY_STATUS_LOADING - Setting the prototype to "nil" will revert back to the original prototype. **Parameters** - `url` (string | hash | url) (optional) - the collection factory component - `prototype` (string | nil) (optional) - the path to the new prototype, or nil **Examples** How to unload the previous prototypes resources, and then spawn a new collection ``` collectionfactory.unload("#factory") -- unload the previous resources collectionfactory.set_prototype("#factory", "/main/levels/level1.collectionc") local ids = collectionfactory.create("#factory", go.get_world_position(), vmath.quat()) ``` ### collectionfactory.STATUS_LOADED *Type:* CONSTANT loaded ### collectionfactory.STATUS_LOADING *Type:* CONSTANT loading ### collectionfactory.STATUS_UNLOADED *Type:* CONSTANT unloaded ### collectionfactory.unload *Type:* FUNCTION This decreases the reference count for each resource loaded with collectionfactory.load. If reference is zero, the resource is destroyed. Calling this function when the factory is not marked as dynamic loading does nothing. **Parameters** - `url` (string | hash | url) (optional) - the collection factory component to unload **Examples** How to unload resources of a collection factory prototype loaded with collectionfactory.load ``` collectionfactory.unload("#factory") ``` # Collection proxy {#apis:collectionproxy-lua} **Namespace:** `collectionproxy` **Language:** Lua **Type:** Defold Lua **File:** `script_collectionproxy.cpp` **Source:** `engine/gamesys/src/gamesys/scripts/script_collectionproxy.cpp` Messages for controlling and interacting with collection proxies which are used to dynamically load collections into the runtime. ## API ### async_load *Type:* MESSAGE Post this message to a collection-proxy-component to start background loading of the referenced collection. When the loading has completed, the message proxy_loaded will be sent back to the script. A loaded collection must be initialized (message init) and enabled (message enable) in order to be simulated and drawn. **Examples** In this example we use a collection proxy to load/unload a level (collection). The example assume the script belongs to an instance with collection-proxy-component with id "proxy". ``` function on_message(self, message_id, message, sender) if message_id == hash("start_level") then -- some script tells us to start loading the level msg.post("#proxy", "async_load") -- store sender for later notification self.loader = sender elseif message_id == hash("proxy_loaded") then -- enable the collection and let the loader know msg.post(sender, "enable") msg.post(self.loader, message_id) end end ``` ### collectionproxy.get_resources *Type:* FUNCTION return an indexed table of resources for a collection proxy where the referenced collection has been excluded using LiveUpdate. Each entry is a hexadecimal string that represents the data of the specific resource. This representation corresponds with the filename for each individual resource that is exported when you bundle an application with LiveUpdate functionality. **Parameters** - `collectionproxy` (url) - the collectionproxy to check for resources. **Returns** - `resources` (table) - the resources, or an empty list if the collection was not excluded. **Examples** ``` local function print_resources(self, cproxy) local resources = collectionproxy.get_resources(cproxy) for _, v in ipairs(resources) do print("Resource: " .. v) end end ``` ### collectionproxy.RESULT_ALREADY_LOADED *Type:* CONSTANT It's impossible to change the collection if the collection is already loaded. ### collectionproxy.RESULT_LOADING *Type:* CONSTANT It's impossible to change the collection while the collection proxy is loading. ### collectionproxy.RESULT_NOT_EXCLUDED *Type:* CONSTANT It's impossible to change the collection for a proxy that isn't excluded. ### collectionproxy.set_collection *Type:* FUNCTION The collection should be loaded by the collection proxy. Setting the collection to "nil" will revert it back to the original collection. The collection proxy shouldn't be loaded and should have the 'Exclude' checkbox checked. This functionality is designed to simplify the management of Live Update resources. **Parameters** - `url` (string | hash | url) (optional) - the collection proxy component - `prototype` (string | nil) (optional) - the path to the new collection, or nil **Returns** - `success` (boolean) - collection change was successful - `code` (number) - one of the collectionproxy.RESULT_* codes if unsuccessful **Examples** The example assume the script belongs to an instance with collection-proxy-component with id "proxy". ``` local ok, error = collectionproxy.set_collection("/go#collectionproxy", "/LU/3.collectionc") if ok then print("The collection has been changed to /LU/3.collectionc") else print("Error changing collection to /LU/3.collectionc ", error) end msg.post("/go#collectionproxy", "load") msg.post("/go#collectionproxy", "init") msg.post("/go#collectionproxy", "enable") ``` ### disable *Type:* MESSAGE Post this message to a collection-proxy-component to disable the referenced collection, which in turn disables the contained game objects and components. **Examples** In this example we use a collection proxy to load/unload a level (collection). The example assumes the script belongs to an instance with a collection-proxy-component with id "proxy". ``` function on_message(self, message_id, message, sender) if message_id == hash("end_level") then local proxy = msg.url("#proxy") msg.post(proxy, "disable") msg.post(proxy, "final") msg.post(proxy, "unload") -- store sender for later notification self.unloader = sender elseif message_id == hash("proxy_unloaded") then -- let unloader know msg.post(self.unloader, "level_ended") end end ``` ### enable *Type:* MESSAGE Post this message to a collection-proxy-component to enable the referenced collection, which in turn enables the contained game objects and components. If the referenced collection was not initialized prior to this call, it will automatically be initialized. **Examples** In this example we use a collection proxy to load/unload a level (collection). The example assume the script belongs to an instance with collection-proxy-component with id "proxy". ``` function on_message(self, message_id, message, sender) if message_id == hash("start_level") then -- some script tells us to start loading the level msg.post("#proxy", "load") -- store sender for later notification self.loader = sender elseif message_id == hash("proxy_loaded") then -- enable the collection and let the loader know msg.post(sender, "enable") msg.post(self.loader, "level_started") end end ``` ### final *Type:* MESSAGE Post this message to a collection-proxy-component to finalize the referenced collection, which in turn finalizes the contained game objects and components. **Examples** In this example we use a collection proxy to load/unload a level (collection). The example assumes the script belongs to an instance with a collection-proxy-component with id "proxy". ``` function on_message(self, message_id, message, sender) if message_id == hash("end_level") then local proxy = msg.url("#proxy") msg.post(proxy, "disable") msg.post(proxy, "final") msg.post(proxy, "unload") -- store sender for later notification self.unloader = sender elseif message_id == hash("proxy_unloaded") then -- let unloader know msg.post(self.unloader, "level_ended") end end ``` ### init *Type:* MESSAGE Post this message to a collection-proxy-component to initialize the game objects and components in the referenced collection. Sending enable to an uninitialized collection proxy automatically initializes it. The init message simply provides a higher level of control. **Examples** In this example we use a collection proxy to load/unload a level (collection). The example assume the script belongs to an instance with collection-proxy-component with id "proxy". ``` function on_message(self, message_id, message, sender) if message_id == hash("load_level") then -- some script tells us to start loading the level msg.post("#proxy", "load") -- store sender for later notification self.loader = sender elseif message_id == hash("proxy_loaded") then -- only initialize the proxy at this point since we want to enable it at a later time for some reason msg.post(sender, "init") -- let loader know msg.post(self.loader, message_id) end end ``` ### load *Type:* MESSAGE Post this message to a collection-proxy-component to start the loading of the referenced collection. When the loading has completed, the message proxy_loaded will be sent back to the script. A loaded collection must be initialized (message init) and enabled (message enable) in order to be simulated and drawn. **Examples** In this example we use a collection proxy to load/unload a level (collection). The example assume the script belongs to an instance with collection-proxy-component with id "proxy". ``` function on_message(self, message_id, message, sender) if message_id == hash("start_level") then -- some script tells us to start loading the level msg.post("#proxy", "load") -- store sender for later notification self.loader = sender elseif message_id == hash("proxy_loaded") then -- enable the collection and let the loader know msg.post(sender, "enable") msg.post(self.loader, message_id) end end ``` ### proxy_loaded *Type:* MESSAGE This message is sent back to the script that initiated a collection proxy load when the referenced collection is loaded. See documentation for load for examples how to use. ### proxy_unloaded *Type:* MESSAGE This message is sent back to the script that initiated an unload with a collection proxy when the referenced collection is unloaded. See documentation for unload for examples how to use. ### set_time_step *Type:* MESSAGE Post this message to a collection-proxy-component to modify the time-step used when updating the collection controlled by the proxy. The time-step is modified by a scaling factor and can be incremented either continuously or in discrete steps. The continuous mode can be used for slow-motion or fast-forward effects. The discrete mode is only useful when scaling the time-step to pass slower than real time (factor is below 1). The time-step will then be set to 0 for as many frames as the scaling demands and then take on the full real-time-step for one frame, to simulate pulses. E.g. if factor is set to 0.1 the time-step would be 0 for 9 frames, then be 1/60 for one frame, 0 for 9 frames, and so on. The result in practice is that the game looks like it's updated at a much lower frequency than 60 Hz, which can be useful for debugging when each frame needs to be inspected. **Parameters** - `factor` (number) - time-step scaling factor - `mode` (number) - time-step mode: 0 for continuous and 1 for discrete **Examples** The examples assumes the script belongs to an instance with a collection-proxy-component with id "proxy". Update the collection twice as fast: ``` msg.post("#proxy", "set_time_step", {factor = 2, mode = 0}) ``` Update the collection twice as slow: ``` msg.post("#proxy", "set_time_step", {factor = 0.5, mode = 0}) ``` Simulate 1 FPS for the collection: ``` msg.post("#proxy", "set_time_step", {factor = 1/60, mode = 1}) ``` ### unload *Type:* MESSAGE Post this message to a collection-proxy-component to start the unloading of the referenced collection. When the unloading has completed, the message proxy_unloaded will be sent back to the script. **Examples** In this example we use a collection proxy to load/unload a level (collection). The example assumes the script belongs to an instance with a collection-proxy-component with id "proxy". ``` function on_message(self, message_id, message, sender) if message_id == hash("end_level") then local proxy = msg.url("#proxy") msg.post(proxy, "disable") msg.post(proxy, "final") msg.post(proxy, "unload") -- store sender for later notification self.unloader = sender elseif message_id == hash("proxy_unloaded") then -- let unloader know msg.post(self.unloader, "level_ended") end end ``` # Coroutine {#apis:coroutine-lua} **Namespace:** `coroutine` **Language:** Lua **Type:** Defold Lua **File:** `lua_coroutine.doc_h` **Source:** `engine/lua/src/lua_coroutine.doc_h` Documentation for the Lua coroutine standard library. From [Lua 5.1 Reference Manual](https://www.lua.org/manual/5.1/) by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes. Copyright © 2006-2012 Lua.org, PUC-Rio. Freely available under the terms of the [Lua license](https://www.lua.org/license.html). ## API ### coroutine.create *Type:* FUNCTION Creates a new coroutine, with body f. f must be a Lua function. Returns this new coroutine, an object with type "thread". **Parameters** - `f` (function) ### coroutine.resume *Type:* FUNCTION Starts or continues the execution of coroutine co. The first time you resume a coroutine, it starts running its body. The values val1, ... are passed as the arguments to the body function. If the coroutine has yielded, resume restarts it; the values val1, ... are passed as the results from the yield. If the coroutine runs without any errors, resume returns true plus any values passed to yield (if the coroutine yields) or any values returned by the body function (if the coroutine terminates). If there is any error, resume returns false plus the error message. **Parameters** - `co` (thread) - `val1` (any) (optional) - `...` (optional) ### coroutine.running *Type:* FUNCTION Returns the running coroutine, or nil when called by the main thread. ### coroutine.status *Type:* FUNCTION Returns the status of coroutine co, as a string: "running", if the coroutine is running (that is, it called status); "suspended", if the coroutine is suspended in a call to yield, or if it has not started running yet; "normal" if the coroutine is active but not running (that is, it has resumed another coroutine); and "dead" if the coroutine has finished its body function, or if it has stopped with an error. **Parameters** - `co` (thread) ### coroutine.wrap *Type:* FUNCTION Creates a new coroutine, with body f. f must be a Lua function. Returns a function that resumes the coroutine each time it is called. Any arguments passed to the function behave as the extra arguments to resume. Returns the same values returned by resume, except the first boolean. In case of error, propagates the error. **Parameters** - `f` (function) ### coroutine.yield *Type:* FUNCTION Suspends the execution of the calling coroutine. The coroutine cannot be running a C function, a metamethod, or an iterator. Any arguments to yield are passed as extra results to resume. **Parameters** - `...` # Crash {#apis:crash-lua} **Namespace:** `crash` **Language:** Lua **Type:** Defold Lua **File:** `script_crash.cpp` **Source:** `engine/crash/src/script_crash.cpp` Native crash logging functions and constants. ## API ### crash.get_backtrace *Type:* FUNCTION A table is returned containing the addresses of the call stack. **Parameters** - `handle` (number) - crash dump handle **Returns** - `backtrace` (table) - table containing the backtrace ### crash.get_extra_data *Type:* FUNCTION The format of read text blob is platform specific and not guaranteed but can be useful for manual inspection. **Parameters** - `handle` (number) - crash dump handle **Returns** - `blob` (string) - string with the platform specific data ### crash.get_modules *Type:* FUNCTION The function returns a table containing entries with sub-tables that have fields 'name' and 'address' set for all loaded modules. **Parameters** - `handle` (number) - crash dump handle **Returns** - `modules` (table) - module table ### crash.get_signum *Type:* FUNCTION read signal number from a crash report **Parameters** - `handle` (number) - crash dump handle **Returns** - `signal` (number) - signal number ### crash.get_sys_field *Type:* FUNCTION reads a system field from a loaded crash dump **Parameters** - `handle` (number) - crash dump handle - `index` (number) - system field enum. Must be less than crash.SYSFIELD_MAX **Returns** - `value` (string | nil) - value recorded in the crash dump, or nil if it didn't exist ### crash.get_user_field *Type:* FUNCTION reads user field from a loaded crash dump **Parameters** - `handle` (number) - crash dump handle - `index` (number) - user data slot index **Returns** - `value` (string) - user data value recorded in the crash dump ### crash.load_previous *Type:* FUNCTION The crash dump will be removed from disk upon a successful load, so loading is one-shot. **Returns** - `handle` (number | nil) - handle to the loaded dump, or nil if no dump was found ### crash.release *Type:* FUNCTION releases a previously loaded crash dump **Parameters** - `handle` (number) - handle to loaded crash dump ### crash.set_file_path *Type:* FUNCTION Crashes occuring before the path is set will be stored to a default engine location. **Parameters** - `path` (string) - file path to use ### crash.set_user_field *Type:* FUNCTION Store a user value that will get written to a crash dump when a crash occurs. This can be user id:s, breadcrumb data etc. There are 32 slots indexed from 0. Each slot stores at most 255 characters. **Parameters** - `index` (number) - slot index. 0-indexed - `value` (string) - string value to store ### crash.SYSFIELD_ANDROID_BUILD_FINGERPRINT *Type:* CONSTANT android build fingerprint ### crash.SYSFIELD_DEVICE_LANGUAGE *Type:* CONSTANT system device language as reported by sys.get_sys_info ### crash.SYSFIELD_DEVICE_MODEL *Type:* CONSTANT device model as reported by sys.get_sys_info ### crash.SYSFIELD_ENGINE_HASH *Type:* CONSTANT engine version as hash ### crash.SYSFIELD_ENGINE_VERSION *Type:* CONSTANT engine version as release number ### crash.SYSFIELD_LANGUAGE *Type:* CONSTANT system language as reported by sys.get_sys_info ### crash.SYSFIELD_MANUFACTURER *Type:* CONSTANT device manufacturer as reported by sys.get_sys_info ### crash.SYSFIELD_MAX *Type:* CONSTANT The max number of sysfields. ### crash.SYSFIELD_SYSTEM_NAME *Type:* CONSTANT system name as reported by sys.get_sys_info ### crash.SYSFIELD_SYSTEM_VERSION *Type:* CONSTANT system version as reported by sys.get_sys_info ### crash.SYSFIELD_TERRITORY *Type:* CONSTANT system territory as reported by sys.get_sys_info ### crash.USERFIELD_MAX *Type:* CONSTANT The max number of user fields. ### crash.USERFIELD_SIZE *Type:* CONSTANT The max size of a single user field. ### crash.write_dump *Type:* FUNCTION Performs the same steps as if a crash had just occured but allows the program to continue. The generated dump can be read by crash.load_previous # Debug {#apis:debug-lua} **Namespace:** `debug` **Language:** Lua **Type:** Defold Lua **File:** `lua_debug.doc_h` **Source:** `engine/lua/src/lua_debug.doc_h` Documentation for the Lua debug standard library. From [Lua 5.1 Reference Manual](https://www.lua.org/manual/5.1/) by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes. Copyright © 2006-2012 Lua.org, PUC-Rio. Freely available under the terms of the [Lua license](https://www.lua.org/license.html). ## API ### debug.debug *Type:* FUNCTION Enters an interactive mode with the user, running each string that the user enters. Using simple commands and other debug facilities, the user can inspect global and local variables, change their values, evaluate expressions, and so on. A line containing only the word cont finishes this function, so that the caller continues its execution. Note that commands for debug.debug are not lexically nested within any function, and so have no direct access to local variables. ### debug.getfenv *Type:* FUNCTION Returns the environment of object o. **Parameters** - `o` (any) ### debug.gethook *Type:* FUNCTION Returns the current hook settings of the thread, as three values: the current hook function, the current hook mask, and the current hook count (as set by the debug.sethook function). **Parameters** - `thread` (thread) (optional) ### debug.getinfo *Type:* FUNCTION Returns a table with information about a function. You can give the function directly, or you can give a number as the value of function, which means the function running at level function of the call stack of the given thread: level 0 is the current function (getinfo itself); level 1 is the function that called getinfo; and so on. If function is a number larger than the number of active functions, then getinfo returns nil. The returned table can contain all the fields returned by lua_getinfo, with the string what describing which fields to fill in. The default for what is to get all information available, except the table of valid lines. If present, the option 'f' adds a field named func with the function itself. If present, the option 'L' adds a field named activelines with the table of valid lines. For instance, the expression debug.getinfo(1,"n").name returns a table with a name for the current function, if a reasonable name can be found, and the expression debug.getinfo(print) returns a table with all available information about the print function. **Parameters** - `thread` (thread) (optional) - `function` (function) - `what` (string) (optional) ### debug.getlocal *Type:* FUNCTION This function returns the name and the value of the local variable with index local of the function at level level of the stack. (The first parameter or local variable has index 1, and so on, until the last active local variable.) The function returns nil if there is no local variable with the given index, and raises an error when called with a level out of range. (You can call debug.getinfo to check whether the level is valid.) Variable names starting with '(' (open parentheses) represent internal variables (loop control variables, temporaries, and C function locals). **Parameters** - `thread` (thread) (optional) - `level` (number) - `local` (number) ### debug.getmetatable *Type:* FUNCTION Returns the metatable of the given object or nil if it does not have a metatable. **Parameters** - `object` (any) ### debug.getregistry *Type:* FUNCTION Returns the registry table . ### debug.getupvalue *Type:* FUNCTION This function returns the name and the value of the upvalue with index up of the function func. The function returns nil if there is no upvalue with the given index. **Parameters** - `func` (function) - `up` (number) ### debug.setfenv *Type:* FUNCTION Sets the environment of the given object to the given table. Returns object. **Parameters** - `object` (any) - `table` (table) ### debug.sethook *Type:* FUNCTION Sets the given function as a hook. The string mask and the number count describe when the hook will be called. The string mask may have the following characters, with the given meaning: "c" the hook is called every time Lua calls a function; "r" the hook is called every time Lua returns from a function; "l" the hook is called every time Lua enters a new line of code. With a count different from zero, the hook is called after every count instructions. When called without arguments, debug.sethook turns off the hook. When the hook is called, its first parameter is a string describing the event that has triggered its call: "call", "return" (or "tail return", when simulating a return from a tail call), "line", and "count". For line events, the hook also gets the new line number as its second parameter. Inside a hook, you can call getinfo with level 2 to get more information about the running function (level 0 is the getinfo function, and level 1 is the hook function), unless the event is "tail return". In this case, Lua is only simulating the return, and a call to getinfo will return invalid data. **Parameters** - `thread` (thread) (optional) - `hook` (function) - `mask` (string) - `count` (number) (optional) ### debug.setlocal *Type:* FUNCTION This function assigns the value value to the local variable with index local of the function at level level of the stack. The function returns nil if there is no local variable with the given index, and raises an error when called with a level out of range. (You can call getinfo to check whether the level is valid.) Otherwise, it returns the name of the local variable. **Parameters** - `thread` (thread) (optional) - `level` (number) - `local` (number) - `value` (any) ### debug.setmetatable *Type:* FUNCTION Sets the metatable for the given object to the given table (which can be nil). **Parameters** - `object` (any) - `table` (table) ### debug.setupvalue *Type:* FUNCTION This function assigns the value value to the upvalue with index up of the function func. The function returns nil if there is no upvalue with the given index. Otherwise, it returns the name of the upvalue. **Parameters** - `func` (function) - `up` (number) - `value` (any) ### debug.traceback *Type:* FUNCTION Returns a string with a traceback of the call stack. An optional message string is appended at the beginning of the traceback. An optional level number tells at which level to start the traceback (default is 1, the function calling traceback). **Parameters** - `thread` (thread) (optional) - `message` (string) (optional) - `level` (number) (optional) # Editor {#apis:editor-lua} **Namespace:** `editor` **Language:** Lua **Type:** Defold Lua **File:** `editor.apidoc` **Source:** `engine/docs/editor.apidoc` Editor scripting documentation ## API ### editor.bob *Type:* FUNCTION Run bob the builder program For the full documentation of the available commands and options, see the bob manual. **Parameters** - `options` (table) (optional) - table of command line options for bob, without the leading dashes (--). You can use snake_case instead of kebab-case for option keys. Only long option names are supported (i.e. output, not o). Supported value types are strings, integers and booleans. If an option takes no arguments, use a boolean (i.e. true). If an option may be repeated, you can use an array of values. - `...commands` (string) (optional) - bob commands, e.g. "resolve" or "build" **Examples** Print help in the console: ``` editor.bob({help = true}) ``` Bundle the game for the host platform: ``` local opts = { archive = true, platform = editor.platform } editor.bob(opts, "distclean", "resolve", "build", "bundle") ``` Using snake_cased and repeated options: ``` local opts = { archive = true, platform = editor.platform, build_server = "https://build.my-company.com", settings = {"test.ini", "headless.ini"} } editor.bob(opts, "distclean", "resolve", "build") ``` ### editor.browse *Type:* FUNCTION Open a URL in the default browser or a registered application **Parameters** - `url` (string) - http(s) or file URL ### editor.can_add *Type:* FUNCTION Check if editor.tx.add() (as well as editor.tx.clear() and editor.tx.remove()) transaction with this property won't throw an error **Parameters** - `node` (string | userdata) - Either resource path (e.g. "/main/game.script"), or internal node id passed to the script by the editor - `property` (string) - Either "path", "text", or a property from the Outline view (hover the label to see its editor script name) **Returns** - `value` (boolean) ### editor.can_get *Type:* FUNCTION Check if you can get this property so editor.get() won't throw an error **Parameters** - `node` (string | userdata) - Either resource path (e.g. "/main/game.script"), or internal node id passed to the script by the editor - `property` (string) - Either "path", "text", or a property from the Outline view (hover the label to see its editor script name) **Returns** - `value` (boolean) ### editor.can_reorder *Type:* FUNCTION Check if editor.tx.reorder() transaction with this property won't throw an error **Parameters** - `node` (string | userdata) - Either resource path (e.g. "/main/game.script"), or internal node id passed to the script by the editor - `property` (string) - Either "path", "text", or a property from the Outline view (hover the label to see its editor script name) **Returns** - `value` (boolean) ### editor.can_reset *Type:* FUNCTION Check if editor.tx.reset() transaction with this property won't throw an error **Parameters** - `node` (string | userdata) - Either resource path (e.g. "/main/game.script"), or internal node id passed to the script by the editor - `property` (string) - Either "path", "text", or a property from the Outline view (hover the label to see its editor script name) **Returns** - `value` (boolean) ### editor.can_set *Type:* FUNCTION Check if editor.tx.set() transaction with this property won't throw an error **Parameters** - `node` (string | userdata) - Either resource path (e.g. "/main/game.script"), or internal node id passed to the script by the editor - `property` (string) - Either "path", "text", or a property from the Outline view (hover the label to see its editor script name) **Returns** - `value` (boolean) ### editor.command *Type:* FUNCTION Create an editor command **Parameters** - `opts` (table) - A table with the following keys:
label string, message
required, user-visible command name, either a string or a localization message
locations string[]
required, a non-empty list of locations where the command is displayed in the editor, values are either "Edit", "View", "Project", "Debug" (the editor menubar), "Assets" (the assets pane), or "Outline" (the outline pane)
query table
optional, a query that both controls the command availability and provides additional information to the command handler functions; a table with the following keys:
selection table
current selection, a table with the following keys:
type string
either "resource" (selected resource) or "outline" (selected outline node)
cardinality string
either "one" (will use first selected item) or "many" (will use all selected items)
argument table
the command argument
id string
optional, keyword identifier that may be used for assigning a shortcut to a command; should be a dot-separated identifier string, e.g. "my-extension.do-stuff"
active function
optional function that additionally checks if a command is active in the current context; will receive opts table with values populated by the query; should be fast to execute since the editor might invoke it in response to UI interactions (on key typed, mouse clicked)
run function
optional function that is invoked when the user decides to execute the command; will receive opts table with values populated by the query
**Returns** - `command` (command) **Examples** Print Git history for a file: ``` editor.command({ label = "Git History", query = { selection = { type = "resource", cardinality = "one" } }, run = function(opts) editor.execute( "git", "log", "--follow", "." .. editor.get(opts.selection, "path"), {reload_resources=false}) end }) ``` ### editor.create_directory *Type:* FUNCTION Create a directory if it does not exist, and all non-existent parent directories. Throws an error if the directory can't be created. **Parameters** - `resource_path` (string) - Resource path (starting with /) **Examples** ``` editor.create_directory("/assets/gen") ``` ### editor.create_resources *Type:* FUNCTION Create resources (including non-existent parent directories). Throws an error if any of the provided resource paths already exist **Parameters** - `resources` (string[) - ] Array of resource paths (strings starting with /) or resource definitions, lua tables with the following keys:
1 string
required, resource path (starting with /)
2 string
optional, created resource content
**Examples** Create a single resource from template: ``` editor.create_resources({ "/npc.go" }) ``` Create multiple resources: ``` editor.create_resources({ "/npc.go", "/levels/1.collection", "/levels/2.collection", }) ``` Create a resource with custom content: ``` editor.create_resources({ {"/npc.script", "go.property('hp', 100)"} }) ``` ### editor.delete_directory *Type:* FUNCTION Delete a directory if it exists, and all existent child directories and files. Throws an error if the directory can't be deleted. **Parameters** - `resource_path` (string) - Resource path (starting with /) **Examples** ``` editor.delete_directory("/assets/gen") ``` ### editor.editor_sha1 *Type:* VARIABLE A string, SHA1 of Defold editor ### editor.engine_sha1 *Type:* VARIABLE A string, SHA1 of Defold engine ### editor.execute *Type:* FUNCTION Execute a shell command. Any shell command arguments should be provided as separate argument strings to this function. If the exit code of the process is not zero, this function throws error. By default, the function returns nil, but it can be configured to capture the output of the shell command as string and return it — set out option to "capture" to do it.By default, after this shell command is executed, the editor will reload resources from disk. **Parameters** - `command` (string) - Shell command name to execute - `...` (string) (optional) - Optional shell command arguments - `options` (table) (optional) - Optional options table. Supported entries:
  • boolean reload_resources: make the editor reload the resources from disk after the command is executed, default true
  • string out: standard output mode, either:
    • "pipe": the output is piped to the editor console (this is the default behavior).
    • "capture": capture and return the output to the editor script with trailing newlines trimmed.
    • "discard": the output is discarded completely.
  • string err: standard error output mode, either:
    • "pipe": the error output is piped to the editor console (this is the default behavior).
    • "stdout": the error output is redirected to the standard output of the process.
    • "discard": the error output is discarded completely.
**Returns** - `result` (nil | string) - If out option is set to "capture", returns the output as string with trimmed trailing newlines. Otherwise, returns nil. **Examples** Make a directory with spaces in it: ``` editor.execute("mkdir", "new dir") ``` Read the git status: ``` local status = editor.execute("git", "status", "--porcelain", { reload_resources = false, out = "capture" }) ``` ### editor.external_file_attributes *Type:* FUNCTION Query information about file system path **Parameters** - `path` (string) - External file path, resolved against project root if relative **Returns** - `attributes` (table) - A table with the following keys:
path string
resolved file path
exists boolean
whether there is a file system entry at the path
is_file boolean
whether the path corresponds to a file
is_directory boolean
whether the path corresponds to a directory
### editor.get *Type:* FUNCTION Get a value of a node property inside the editor. Some properties might be read-only, and some might be unavailable in different contexts, so you should use editor.can_get() before reading them and editor.can_set() before making the editor set them. **Parameters** - `node` (string | userdata) - Either resource path (e.g. "/main/game.script"), or internal node id passed to the script by the editor - `property` (string) - Either "path", "text", or a property from the Outline view (hover the label to see its editor script name) **Returns** - `value` (any) - property value ### editor.open_external_file *Type:* FUNCTION Open a file in a registered application **Parameters** - `path` (string) - file path ### editor.platform *Type:* VARIABLE Editor platform id. A string, either: - "x86_64-win32" - "x86_64-macos" - "arm64-macos" - "x86_64-linux" ### editor.prefs.get *Type:* FUNCTION Get preference value The schema for the preference value should be defined beforehand. **Parameters** - `key` (string) - dot-separated preference key path **Returns** - `value` (any) - current pref value or default if a schema for the key path exists, nil otherwise ### editor.prefs.is_set *Type:* FUNCTION Check if preference value is explicitly set The schema for the preference value should be defined beforehand. **Parameters** - `key` (string) - dot-separated preference key path **Returns** - `value` (boolean) - flag indicating if the value is explicitly set ### editor.prefs.schema.array *Type:* FUNCTION array schema **Parameters** - `opts` (table) - Required opts:
item schema
array item schema
Optional opts:
default item[]
default value
scope string
preference scope; either:
  • editor.prefs.SCOPE.GLOBAL: same preference value is used in every project on this computer
  • editor.prefs.SCOPE.PROJECT: a separate preference value per project
**Returns** - `value` (schema) - Prefs schema ### editor.prefs.schema.boolean *Type:* FUNCTION boolean schema **Parameters** - `opts` (table) (optional) - Optional opts:
default boolean
default value
scope string
preference scope; either:
  • editor.prefs.SCOPE.GLOBAL: same preference value is used in every project on this computer
  • editor.prefs.SCOPE.PROJECT: a separate preference value per project
**Returns** - `value` (schema) - Prefs schema ### editor.prefs.schema.enum *Type:* FUNCTION enum value schema **Parameters** - `opts` (table) - Required opts:
values any[]
allowed values, must be scalar (nil, boolean, number or string)
Optional opts:
default any
default value
scope string
preference scope; either:
  • editor.prefs.SCOPE.GLOBAL: same preference value is used in every project on this computer
  • editor.prefs.SCOPE.PROJECT: a separate preference value per project
**Returns** - `value` (schema) - Prefs schema ### editor.prefs.schema.integer *Type:* FUNCTION integer schema **Parameters** - `opts` (table) (optional) - Optional opts:
default integer
default value
scope string
preference scope; either:
  • editor.prefs.SCOPE.GLOBAL: same preference value is used in every project on this computer
  • editor.prefs.SCOPE.PROJECT: a separate preference value per project
**Returns** - `value` (schema) - Prefs schema ### editor.prefs.schema.keyword *Type:* FUNCTION keyword schema A keyword is a short string that is interned within the editor runtime, useful e.g. for identifiers **Parameters** - `opts` (table) (optional) - Optional opts:
default string
default value
scope string
preference scope; either:
  • editor.prefs.SCOPE.GLOBAL: same preference value is used in every project on this computer
  • editor.prefs.SCOPE.PROJECT: a separate preference value per project
**Returns** - `value` (schema) - Prefs schema ### editor.prefs.schema.number *Type:* FUNCTION floating-point number schema **Parameters** - `opts` (table) (optional) - Optional opts:
default number
default value
scope string
preference scope; either:
  • editor.prefs.SCOPE.GLOBAL: same preference value is used in every project on this computer
  • editor.prefs.SCOPE.PROJECT: a separate preference value per project
**Returns** - `value` (schema) - Prefs schema ### editor.prefs.schema.object *Type:* FUNCTION heterogeneous object schema **Parameters** - `opts` (table) - Required opts:
properties table<string, schema>
a table from property key (string) to value schema
Optional opts:
default table
default value
scope string
preference scope; either:
  • editor.prefs.SCOPE.GLOBAL: same preference value is used in every project on this computer
  • editor.prefs.SCOPE.PROJECT: a separate preference value per project
**Returns** - `value` (schema) - Prefs schema ### editor.prefs.schema.object_of *Type:* FUNCTION homogeneous object schema **Parameters** - `opts` (table) - Required opts:
key schema
table key schema
val schema
table value schema
Optional opts:
default table
default value
scope string
preference scope; either:
  • editor.prefs.SCOPE.GLOBAL: same preference value is used in every project on this computer
  • editor.prefs.SCOPE.PROJECT: a separate preference value per project
**Returns** - `value` (schema) - Prefs schema ### editor.prefs.schema.one_of *Type:* FUNCTION one of schema **Parameters** - `opts` (table) - Required opts:
schemas schema[]
alternative schemas
Optional opts:
default any
default value
scope string
preference scope; either:
  • editor.prefs.SCOPE.GLOBAL: same preference value is used in every project on this computer
  • editor.prefs.SCOPE.PROJECT: a separate preference value per project
**Returns** - `value` (schema) - Prefs schema ### editor.prefs.schema.password *Type:* FUNCTION password schema A password is a string that is encrypted when stored in a preference file **Parameters** - `opts` (table) (optional) - Optional opts:
default string
default value
scope string
preference scope; either:
  • editor.prefs.SCOPE.GLOBAL: same preference value is used in every project on this computer
  • editor.prefs.SCOPE.PROJECT: a separate preference value per project
**Returns** - `value` (schema) - Prefs schema ### editor.prefs.schema.set *Type:* FUNCTION set schema Set is represented as a lua table with true values **Parameters** - `opts` (table) - Required opts:
item schema
set item schema
Optional opts:
default table<item, true>
default value
scope string
preference scope; either:
  • editor.prefs.SCOPE.GLOBAL: same preference value is used in every project on this computer
  • editor.prefs.SCOPE.PROJECT: a separate preference value per project
**Returns** - `value` (schema) - Prefs schema ### editor.prefs.schema.string *Type:* FUNCTION string schema **Parameters** - `opts` (table) (optional) - Optional opts:
default string
default value
scope string
preference scope; either:
  • editor.prefs.SCOPE.GLOBAL: same preference value is used in every project on this computer
  • editor.prefs.SCOPE.PROJECT: a separate preference value per project
**Returns** - `value` (schema) - Prefs schema ### editor.prefs.schema.tuple *Type:* FUNCTION tuple schema A tuple is a fixed-length array where each item has its own defined type **Parameters** - `opts` (table) - Required opts:
items schema[]
schemas for the items
Optional opts:
default any[]
default value
scope string
preference scope; either:
  • editor.prefs.SCOPE.GLOBAL: same preference value is used in every project on this computer
  • editor.prefs.SCOPE.PROJECT: a separate preference value per project
**Returns** - `value` (schema) - Prefs schema ### editor.prefs.SCOPE.GLOBAL *Type:* VARIABLE "global" ### editor.prefs.SCOPE.PROJECT *Type:* VARIABLE "project" ### editor.prefs.set *Type:* FUNCTION Set preference value The schema for the preference value should be defined beforehand. **Parameters** - `key` (string) - dot-separated preference key path - `value` (any) - new pref value to set ### editor.properties *Type:* FUNCTION List property names for a node. The result is context-sensitive and can vary by node/resource type and editor state. Returned names are readable with editor.get(node, property). Mutating capabilities are per-property; use editor.can_set(), editor.can_reset(), editor.can_add(), and editor.can_reorder() to check which operations are supported. **Parameters** - `node` (string | userdata) - Either resource path (e.g. "/main/game.script"), or internal node id passed to the script by the editor **Returns** - `properties` (string[) - ] sorted unique editor property names available in the current context ### editor.resource_attributes *Type:* FUNCTION Query information about a project resource **Parameters** - `resource_path` (string) - Resource path (starting with /) **Returns** - `value` (table) - A table with the following keys:
exists boolean
whether a resource identified by the path exists in the project
is_file boolean
whether the resource represents a file with some content
is_directory boolean
whether the resource represents a directory
### editor.save *Type:* FUNCTION Persist any unsaved changes to disk ### editor.transact *Type:* FUNCTION Change the editor state in a single, undoable transaction **Parameters** - `txs` (transaction_step[) - ] An array of transaction steps created using editor.tx.* functions ### editor.tx.add *Type:* FUNCTION Create a transaction step that will add a child item to a node's list property when transacted with editor.transact(). **Parameters** - `node` (string | userdata) - Either resource path (e.g. "/main/game.script"), or internal node id passed to the script by the editor - `property` (string) - Either "path", "text", or a property from the Outline view (hover the label to see its editor script name) - `value` (any) - Added item for the property, a table from property key to either a valid editor.tx.set()-able value, or an array of valid editor.tx.add()-able values ### editor.tx.clear *Type:* FUNCTION Create a transaction step that will remove all items from node's list property when transacted with editor.transact(). **Parameters** - `node` (string | userdata) - Either resource path (e.g. "/main/game.script"), or internal node id passed to the script by the editor - `property` (string) - Either "path", "text", or a property from the Outline view (hover the label to see its editor script name) **Returns** - `tx` (transaction_step) - A transaction step ### editor.tx.remove *Type:* FUNCTION Create a transaction step that will remove a child node from the node's list property when transacted with editor.transact(). **Parameters** - `node` (string | userdata) - Either resource path (e.g. "/main/game.script"), or internal node id passed to the script by the editor - `property` (string) - Either "path", "text", or a property from the Outline view (hover the label to see its editor script name) - `child_node` (string | userdata) - Either resource path (e.g. "/main/game.script"), or internal node id passed to the script by the editor **Returns** - `tx` (transaction_step) - A transaction step ### editor.tx.reorder *Type:* FUNCTION Create a transaction step that reorders child nodes in a node list defined by the property if supported (see editor.can_reorder()) **Parameters** - `node` (string | userdata) - Either resource path (e.g. "/main/game.script"), or internal node id passed to the script by the editor - `property` (string) - Either "path", "text", or a property from the Outline view (hover the label to see its editor script name) - `child_nodes` (table) - array of child nodes (the same as returned by editor.get(node, property)) in new order **Returns** - `tx` (transaction_step) - A transaction step ### editor.tx.reset *Type:* FUNCTION Create a transaction step that will reset an overridden property to its default value when transacted with editor.transact(). **Parameters** - `node` (string | userdata) - Either resource path (e.g. "/main/game.script"), or internal node id passed to the script by the editor - `property` (string) - Either "path", "text", or a property from the Outline view (hover the label to see its editor script name) **Returns** - `tx` (transaction_step) - A transaction step ### editor.tx.set *Type:* FUNCTION Create transaction step that will set the node's property to a supplied value when transacted with editor.transact(). **Parameters** - `node` (string | userdata) - Either resource path (e.g. "/main/game.script"), or internal node id passed to the script by the editor - `property` (string) - Either "path", "text", or a property from the Outline view (hover the label to see its editor script name) - `value` (any) - A new value for the property **Returns** - `tx` (transaction_step) - A transaction step ### editor.ui.ALIGNMENT.BOTTOM *Type:* VARIABLE "bottom" ### editor.ui.ALIGNMENT.BOTTOM_LEFT *Type:* VARIABLE "bottom-left" ### editor.ui.ALIGNMENT.BOTTOM_RIGHT *Type:* VARIABLE "bottom-right" ### editor.ui.ALIGNMENT.CENTER *Type:* VARIABLE "center" ### editor.ui.ALIGNMENT.LEFT *Type:* VARIABLE "left" ### editor.ui.ALIGNMENT.RIGHT *Type:* VARIABLE "right" ### editor.ui.ALIGNMENT.TOP *Type:* VARIABLE "top" ### editor.ui.ALIGNMENT.TOP_LEFT *Type:* VARIABLE "top-left" ### editor.ui.ALIGNMENT.TOP_RIGHT *Type:* VARIABLE "top-right" ### editor.ui.button *Type:* FUNCTION Button with a label and/or an icon **Parameters** - `props` (table) - Optional props:
on_pressed function
button press callback, will be invoked without arguments when the user presses the button
text string, message
the text, either a string or a localization message
text_alignment string
text alignment within paragraph bounds; either:
  • editor.ui.TEXT_ALIGNMENT.LEFT
  • editor.ui.TEXT_ALIGNMENT.CENTER
  • editor.ui.TEXT_ALIGNMENT.RIGHT
  • editor.ui.TEXT_ALIGNMENT.JUSTIFY
icon string
predefined icon name; either:
  • editor.ui.ICON.OPEN_RESOURCE
  • editor.ui.ICON.PLUS
  • editor.ui.ICON.MINUS
  • editor.ui.ICON.CLEAR
enabled boolean
determines if the input component can be interacted with
alignment string
alignment of the component content within its assigned bounds, defaults to editor.ui.ALIGNMENT.TOP_LEFT; either:
  • editor.ui.ALIGNMENT.TOP_LEFT
  • editor.ui.ALIGNMENT.TOP
  • editor.ui.ALIGNMENT.TOP_RIGHT
  • editor.ui.ALIGNMENT.LEFT
  • editor.ui.ALIGNMENT.CENTER
  • editor.ui.ALIGNMENT.RIGHT
  • editor.ui.ALIGNMENT.BOTTOM_LEFT
  • editor.ui.ALIGNMENT.BOTTOM
  • editor.ui.ALIGNMENT.BOTTOM_RIGHT
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.ui.check_box *Type:* FUNCTION Check box with a label **Parameters** - `props` (table) - Optional props:
value boolean
determines if the checkbox should appear checked
on_value_changed function
change callback, will receive the new value
text string, message
the text, either a string or a localization message
text_alignment string
text alignment within paragraph bounds; either:
  • editor.ui.TEXT_ALIGNMENT.LEFT
  • editor.ui.TEXT_ALIGNMENT.CENTER
  • editor.ui.TEXT_ALIGNMENT.RIGHT
  • editor.ui.TEXT_ALIGNMENT.JUSTIFY
issue table
issue related to the input; table with the following keys (all required):
severity string
either editor.ui.ISSUE_SEVERITY.WARNING or editor.ui.ISSUE_SEVERITY.ERROR
message string, message
issue message that will be shown in a tooltip; either a string or a localization message
tooltip string, message
tooltip message shown on hover; either a string or a localization message
enabled boolean
determines if the input component can be interacted with
alignment string
alignment of the component content within its assigned bounds, defaults to editor.ui.ALIGNMENT.TOP_LEFT; either:
  • editor.ui.ALIGNMENT.TOP_LEFT
  • editor.ui.ALIGNMENT.TOP
  • editor.ui.ALIGNMENT.TOP_RIGHT
  • editor.ui.ALIGNMENT.LEFT
  • editor.ui.ALIGNMENT.CENTER
  • editor.ui.ALIGNMENT.RIGHT
  • editor.ui.ALIGNMENT.BOTTOM_LEFT
  • editor.ui.ALIGNMENT.BOTTOM
  • editor.ui.ALIGNMENT.BOTTOM_RIGHT
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.ui.COLOR.ERROR *Type:* VARIABLE "error" ### editor.ui.COLOR.HINT *Type:* VARIABLE "hint" ### editor.ui.COLOR.OVERRIDE *Type:* VARIABLE "override" ### editor.ui.COLOR.TEXT *Type:* VARIABLE "text" ### editor.ui.COLOR.WARNING *Type:* VARIABLE "warning" ### editor.ui.component *Type:* FUNCTION Convert a function to a UI component. The wrapped function may call any hooks functions (editor.ui.use_*), but on any function invocation, the hooks calls must be the same, and in the same order. This means that hooks should not be used inside loops and conditions or after a conditional return statement. The following props are supported automatically:grow booleandetermines if the component should grow to fill available space in a horizontal or vertical layout containerrow_span integerhow many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.column_span integerhow many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container. **Parameters** - `fn` (function) - function, will receive a single table of props when called **Returns** - `value` (function) - decorated component function that may be invoked with a props table create component ### editor.ui.dialog *Type:* FUNCTION Dialog component, a top-level window component that can't be used as a child of other components **Parameters** - `props` (table) - Required props:
title string, message
OS dialog window title, either a string or a localization message
Optional props:
header component
top part of the dialog, defaults to editor.ui.heading({text = props.title})
content component
content of the dialog
buttons component[]
array of editor.ui.dialog_button(...) components, footer of the dialog. Defaults to a single Close button
**Returns** - `value` (component) - UI component ### editor.ui.dialog_button *Type:* FUNCTION Dialog button shown in the footer of a dialog **Parameters** - `props` (table) - Required props:
text string, message
button text, either a string or a localization message
Optional props:
result any
value returned by editor.ui.show_dialog(...) if this button is pressed
default boolean
if set, pressing Enter in the dialog will trigger this button
cancel boolean
if set, pressing Escape in the dialog will trigger this button
enabled boolean
determines if the button can be interacted with
**Returns** - `value` (component) - UI component ### editor.ui.external_file_field *Type:* FUNCTION Input component for selecting files from the file system **Parameters** - `props` (table) - Optional props:
value string
file or directory path; resolved against project root if relative
on_value_changed function
value change callback, will receive the absolute path of a selected file/folder or nil if the field was cleared; even though the selector dialog allows selecting only files, it's possible to receive directories and non-existent file system entries using text field input
title string, message
OS window title, either a string or a localization message
filters table[]
File filters, an array of filter tables, where each filter has following keys:
description string, message
text explaining the filter, either a literal string like "Text files (.txt)" or a localization message
extensions string[]
array of file extension patterns, e.g. ".txt", "." or "game.project"
issue table
issue related to the input; table with the following keys (all required):
severity string
either editor.ui.ISSUE_SEVERITY.WARNING or editor.ui.ISSUE_SEVERITY.ERROR
message string, message
issue message that will be shown in a tooltip; either a string or a localization message
tooltip string, message
tooltip message shown on hover; either a string or a localization message
enabled boolean
determines if the input component can be interacted with
alignment string
alignment of the component content within its assigned bounds, defaults to editor.ui.ALIGNMENT.TOP_LEFT; either:
  • editor.ui.ALIGNMENT.TOP_LEFT
  • editor.ui.ALIGNMENT.TOP
  • editor.ui.ALIGNMENT.TOP_RIGHT
  • editor.ui.ALIGNMENT.LEFT
  • editor.ui.ALIGNMENT.CENTER
  • editor.ui.ALIGNMENT.RIGHT
  • editor.ui.ALIGNMENT.BOTTOM_LEFT
  • editor.ui.ALIGNMENT.BOTTOM
  • editor.ui.ALIGNMENT.BOTTOM_RIGHT
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.ui.grid *Type:* FUNCTION Layout container that places its children in a 2D grid **Parameters** - `props` (table) - Optional props:
children component[][]
array of arrays of child components
rows table[]
array of row option tables, separate configuration for each row:
grow boolean
determines if the row should grow to fill available space
columns table[]
array of column option tables, separate configuration for each column:
grow boolean
determines if the column should grow to fill available space
padding string, number
empty space from the edges of the container to its children; either:
  • editor.ui.PADDING.NONE
  • editor.ui.PADDING.SMALL
  • editor.ui.PADDING.MEDIUM
  • editor.ui.PADDING.LARGE
  • non-negative number, pixels
spacing string, number
empty space between child components, defaults to editor.ui.SPACING.MEDIUM; either:
  • editor.ui.SPACING.NONE
  • editor.ui.SPACING.SMALL
  • editor.ui.SPACING.MEDIUM
  • editor.ui.SPACING.LARGE
  • non-negative number, pixels
alignment string
alignment of the component content within its assigned bounds, defaults to editor.ui.ALIGNMENT.TOP_LEFT; either:
  • editor.ui.ALIGNMENT.TOP_LEFT
  • editor.ui.ALIGNMENT.TOP
  • editor.ui.ALIGNMENT.TOP_RIGHT
  • editor.ui.ALIGNMENT.LEFT
  • editor.ui.ALIGNMENT.CENTER
  • editor.ui.ALIGNMENT.RIGHT
  • editor.ui.ALIGNMENT.BOTTOM_LEFT
  • editor.ui.ALIGNMENT.BOTTOM
  • editor.ui.ALIGNMENT.BOTTOM_RIGHT
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.ui.heading *Type:* FUNCTION A text heading **Parameters** - `props` (table) - Optional props:
text string, message
the text, either a string or a localization message
text_alignment string
text alignment within paragraph bounds; either:
  • editor.ui.TEXT_ALIGNMENT.LEFT
  • editor.ui.TEXT_ALIGNMENT.CENTER
  • editor.ui.TEXT_ALIGNMENT.RIGHT
  • editor.ui.TEXT_ALIGNMENT.JUSTIFY
color string
semantic color, defaults to editor.ui.COLOR.TEXT; either:
  • editor.ui.COLOR.TEXT
  • editor.ui.COLOR.HINT
  • editor.ui.COLOR.OVERRIDE
  • editor.ui.COLOR.WARNING
  • editor.ui.COLOR.ERROR
word_wrap boolean
determines if the lines of text are word-wrapped when they don't fit in the assigned bounds, defaults to true
style string
heading style, defaults to editor.ui.HEADING_STYLE.H3; either:
  • editor.ui.HEADING_STYLE.H1
  • editor.ui.HEADING_STYLE.H2
  • editor.ui.HEADING_STYLE.H3
  • editor.ui.HEADING_STYLE.H4
  • editor.ui.HEADING_STYLE.H5
  • editor.ui.HEADING_STYLE.H6
  • editor.ui.HEADING_STYLE.DIALOG
  • editor.ui.HEADING_STYLE.FORM
alignment string
alignment of the component content within its assigned bounds, defaults to editor.ui.ALIGNMENT.TOP_LEFT; either:
  • editor.ui.ALIGNMENT.TOP_LEFT
  • editor.ui.ALIGNMENT.TOP
  • editor.ui.ALIGNMENT.TOP_RIGHT
  • editor.ui.ALIGNMENT.LEFT
  • editor.ui.ALIGNMENT.CENTER
  • editor.ui.ALIGNMENT.RIGHT
  • editor.ui.ALIGNMENT.BOTTOM_LEFT
  • editor.ui.ALIGNMENT.BOTTOM
  • editor.ui.ALIGNMENT.BOTTOM_RIGHT
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.ui.HEADING_STYLE.DIALOG *Type:* VARIABLE "dialog" ### editor.ui.HEADING_STYLE.FORM *Type:* VARIABLE "form" ### editor.ui.HEADING_STYLE.H1 *Type:* VARIABLE "h1" ### editor.ui.HEADING_STYLE.H2 *Type:* VARIABLE "h2" ### editor.ui.HEADING_STYLE.H3 *Type:* VARIABLE "h3" ### editor.ui.HEADING_STYLE.H4 *Type:* VARIABLE "h4" ### editor.ui.HEADING_STYLE.H5 *Type:* VARIABLE "h5" ### editor.ui.HEADING_STYLE.H6 *Type:* VARIABLE "h6" ### editor.ui.horizontal *Type:* FUNCTION Layout container that places its children in a horizontal row one after another **Parameters** - `props` (table) - Optional props:
children component[]
array of child components
padding string, number
empty space from the edges of the container to its children; either:
  • editor.ui.PADDING.NONE
  • editor.ui.PADDING.SMALL
  • editor.ui.PADDING.MEDIUM
  • editor.ui.PADDING.LARGE
  • non-negative number, pixels
spacing string, number
empty space between child components, defaults to editor.ui.SPACING.MEDIUM; either:
  • editor.ui.SPACING.NONE
  • editor.ui.SPACING.SMALL
  • editor.ui.SPACING.MEDIUM
  • editor.ui.SPACING.LARGE
  • non-negative number, pixels
alignment string
alignment of the component content within its assigned bounds, defaults to editor.ui.ALIGNMENT.TOP_LEFT; either:
  • editor.ui.ALIGNMENT.TOP_LEFT
  • editor.ui.ALIGNMENT.TOP
  • editor.ui.ALIGNMENT.TOP_RIGHT
  • editor.ui.ALIGNMENT.LEFT
  • editor.ui.ALIGNMENT.CENTER
  • editor.ui.ALIGNMENT.RIGHT
  • editor.ui.ALIGNMENT.BOTTOM_LEFT
  • editor.ui.ALIGNMENT.BOTTOM
  • editor.ui.ALIGNMENT.BOTTOM_RIGHT
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.ui.icon *Type:* FUNCTION An icon from a predefined set **Parameters** - `props` (table) - Required props:
icon string
predefined icon name; either:
  • editor.ui.ICON.OPEN_RESOURCE
  • editor.ui.ICON.PLUS
  • editor.ui.ICON.MINUS
  • editor.ui.ICON.CLEAR
Optional props:
alignment string
alignment of the component content within its assigned bounds, defaults to editor.ui.ALIGNMENT.TOP_LEFT; either:
  • editor.ui.ALIGNMENT.TOP_LEFT
  • editor.ui.ALIGNMENT.TOP
  • editor.ui.ALIGNMENT.TOP_RIGHT
  • editor.ui.ALIGNMENT.LEFT
  • editor.ui.ALIGNMENT.CENTER
  • editor.ui.ALIGNMENT.RIGHT
  • editor.ui.ALIGNMENT.BOTTOM_LEFT
  • editor.ui.ALIGNMENT.BOTTOM
  • editor.ui.ALIGNMENT.BOTTOM_RIGHT
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.ui.ICON.CLEAR *Type:* VARIABLE "clear" ### editor.ui.ICON.MINUS *Type:* VARIABLE "minus" ### editor.ui.ICON.OPEN_RESOURCE *Type:* VARIABLE "open-resource" ### editor.ui.ICON.PLUS *Type:* VARIABLE "plus" ### editor.ui.image *Type:* FUNCTION An image **Parameters** - `props` (table) - Required props:
image string
either a resource path (starts with /), or an URL
Optional props:
width number
width of the image view, the image will be fit inside it while preserving its aspect ratio
height number
height of the image view, the image will be fit inside it while preserving its aspect ratio
alignment string
alignment of the component content within its assigned bounds, defaults to editor.ui.ALIGNMENT.TOP_LEFT; either:
  • editor.ui.ALIGNMENT.TOP_LEFT
  • editor.ui.ALIGNMENT.TOP
  • editor.ui.ALIGNMENT.TOP_RIGHT
  • editor.ui.ALIGNMENT.LEFT
  • editor.ui.ALIGNMENT.CENTER
  • editor.ui.ALIGNMENT.RIGHT
  • editor.ui.ALIGNMENT.BOTTOM_LEFT
  • editor.ui.ALIGNMENT.BOTTOM
  • editor.ui.ALIGNMENT.BOTTOM_RIGHT
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.ui.integer_field *Type:* FUNCTION Integer input component based on a text field, reports changes on commit (Enter or focus loss) **Parameters** - `props` (table) - Optional props:
value any
value
on_value_changed function
value change callback, will receive the new value
issue table
issue related to the input; table with the following keys (all required):
severity string
either editor.ui.ISSUE_SEVERITY.WARNING or editor.ui.ISSUE_SEVERITY.ERROR
message string, message
issue message that will be shown in a tooltip; either a string or a localization message
tooltip string, message
tooltip message shown on hover; either a string or a localization message
enabled boolean
determines if the input component can be interacted with
alignment string
alignment of the component content within its assigned bounds, defaults to editor.ui.ALIGNMENT.TOP_LEFT; either:
  • editor.ui.ALIGNMENT.TOP_LEFT
  • editor.ui.ALIGNMENT.TOP
  • editor.ui.ALIGNMENT.TOP_RIGHT
  • editor.ui.ALIGNMENT.LEFT
  • editor.ui.ALIGNMENT.CENTER
  • editor.ui.ALIGNMENT.RIGHT
  • editor.ui.ALIGNMENT.BOTTOM_LEFT
  • editor.ui.ALIGNMENT.BOTTOM
  • editor.ui.ALIGNMENT.BOTTOM_RIGHT
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.ui.ISSUE_SEVERITY.ERROR *Type:* VARIABLE "error" ### editor.ui.ISSUE_SEVERITY.WARNING *Type:* VARIABLE "warning" ### editor.ui.label *Type:* FUNCTION Label intended for use with input components **Parameters** - `props` (table) - Optional props:
text string, message
the text, either a string or a localization message
text_alignment string
text alignment within paragraph bounds; either:
  • editor.ui.TEXT_ALIGNMENT.LEFT
  • editor.ui.TEXT_ALIGNMENT.CENTER
  • editor.ui.TEXT_ALIGNMENT.RIGHT
  • editor.ui.TEXT_ALIGNMENT.JUSTIFY
color string
semantic color, defaults to editor.ui.COLOR.TEXT; either:
  • editor.ui.COLOR.TEXT
  • editor.ui.COLOR.HINT
  • editor.ui.COLOR.OVERRIDE
  • editor.ui.COLOR.WARNING
  • editor.ui.COLOR.ERROR
tooltip string, message
tooltip message shown on hover; either a string or a localization message
alignment string
alignment of the component content within its assigned bounds, defaults to editor.ui.ALIGNMENT.TOP_LEFT; either:
  • editor.ui.ALIGNMENT.TOP_LEFT
  • editor.ui.ALIGNMENT.TOP
  • editor.ui.ALIGNMENT.TOP_RIGHT
  • editor.ui.ALIGNMENT.LEFT
  • editor.ui.ALIGNMENT.CENTER
  • editor.ui.ALIGNMENT.RIGHT
  • editor.ui.ALIGNMENT.BOTTOM_LEFT
  • editor.ui.ALIGNMENT.BOTTOM
  • editor.ui.ALIGNMENT.BOTTOM_RIGHT
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.ui.number_field *Type:* FUNCTION Number input component based on a text field, reports changes on commit (Enter or focus loss) **Parameters** - `props` (table) - Optional props:
value any
value
on_value_changed function
value change callback, will receive the new value
issue table
issue related to the input; table with the following keys (all required):
severity string
either editor.ui.ISSUE_SEVERITY.WARNING or editor.ui.ISSUE_SEVERITY.ERROR
message string, message
issue message that will be shown in a tooltip; either a string or a localization message
tooltip string, message
tooltip message shown on hover; either a string or a localization message
enabled boolean
determines if the input component can be interacted with
alignment string
alignment of the component content within its assigned bounds, defaults to editor.ui.ALIGNMENT.TOP_LEFT; either:
  • editor.ui.ALIGNMENT.TOP_LEFT
  • editor.ui.ALIGNMENT.TOP
  • editor.ui.ALIGNMENT.TOP_RIGHT
  • editor.ui.ALIGNMENT.LEFT
  • editor.ui.ALIGNMENT.CENTER
  • editor.ui.ALIGNMENT.RIGHT
  • editor.ui.ALIGNMENT.BOTTOM_LEFT
  • editor.ui.ALIGNMENT.BOTTOM
  • editor.ui.ALIGNMENT.BOTTOM_RIGHT
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.ui.open_resource *Type:* FUNCTION Open a resource, either in the editor or in a third-party app **Parameters** - `resource_path` (string) - Resource path (starting with /) ### editor.ui.ORIENTATION.HORIZONTAL *Type:* VARIABLE "horizontal" ### editor.ui.ORIENTATION.VERTICAL *Type:* VARIABLE "vertical" ### editor.ui.PADDING.LARGE *Type:* VARIABLE "large" ### editor.ui.PADDING.MEDIUM *Type:* VARIABLE "medium" ### editor.ui.PADDING.NONE *Type:* VARIABLE "none" ### editor.ui.PADDING.SMALL *Type:* VARIABLE "small" ### editor.ui.paragraph *Type:* FUNCTION A paragraph of text **Parameters** - `props` (table) - Optional props:
text string, message
the text, either a string or a localization message
text_alignment string
text alignment within paragraph bounds; either:
  • editor.ui.TEXT_ALIGNMENT.LEFT
  • editor.ui.TEXT_ALIGNMENT.CENTER
  • editor.ui.TEXT_ALIGNMENT.RIGHT
  • editor.ui.TEXT_ALIGNMENT.JUSTIFY
color string
semantic color, defaults to editor.ui.COLOR.TEXT; either:
  • editor.ui.COLOR.TEXT
  • editor.ui.COLOR.HINT
  • editor.ui.COLOR.OVERRIDE
  • editor.ui.COLOR.WARNING
  • editor.ui.COLOR.ERROR
word_wrap boolean
determines if the lines of text are word-wrapped when they don't fit in the assigned bounds, defaults to true
alignment string
alignment of the component content within its assigned bounds, defaults to editor.ui.ALIGNMENT.TOP_LEFT; either:
  • editor.ui.ALIGNMENT.TOP_LEFT
  • editor.ui.ALIGNMENT.TOP
  • editor.ui.ALIGNMENT.TOP_RIGHT
  • editor.ui.ALIGNMENT.LEFT
  • editor.ui.ALIGNMENT.CENTER
  • editor.ui.ALIGNMENT.RIGHT
  • editor.ui.ALIGNMENT.BOTTOM_LEFT
  • editor.ui.ALIGNMENT.BOTTOM
  • editor.ui.ALIGNMENT.BOTTOM_RIGHT
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.ui.resource_field *Type:* FUNCTION Input component for selecting project resources **Parameters** - `props` (table) - Optional props:
value string
resource path (must start with /)
on_value_changed function
value change callback, will receive either resource path of a selected resource or nil when the field is cleared; even though the resource selector dialog allows filtering on resource extensions, it's possible to receive resources with other extensions and non-existent resources using text field input
title string, message
dialog title, either a string or a localization message, defaults to localization.message("dialog.select-resource.title")
extensions string[]
if specified, restricts selectable resources in the dialog to specified file extensions; e.g. {"collection", "go"}
issue table
issue related to the input; table with the following keys (all required):
severity string
either editor.ui.ISSUE_SEVERITY.WARNING or editor.ui.ISSUE_SEVERITY.ERROR
message string, message
issue message that will be shown in a tooltip; either a string or a localization message
tooltip string, message
tooltip message shown on hover; either a string or a localization message
enabled boolean
determines if the input component can be interacted with
alignment string
alignment of the component content within its assigned bounds, defaults to editor.ui.ALIGNMENT.TOP_LEFT; either:
  • editor.ui.ALIGNMENT.TOP_LEFT
  • editor.ui.ALIGNMENT.TOP
  • editor.ui.ALIGNMENT.TOP_RIGHT
  • editor.ui.ALIGNMENT.LEFT
  • editor.ui.ALIGNMENT.CENTER
  • editor.ui.ALIGNMENT.RIGHT
  • editor.ui.ALIGNMENT.BOTTOM_LEFT
  • editor.ui.ALIGNMENT.BOTTOM
  • editor.ui.ALIGNMENT.BOTTOM_RIGHT
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.ui.scroll *Type:* FUNCTION Layout container that optionally shows scroll bars if child contents overflow the assigned bounds **Parameters** - `props` (table) - Required props:
content component
content component
Optional props:
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.ui.select_box *Type:* FUNCTION Dropdown select box with an array of options **Parameters** - `props` (table) - Optional props:
value any
selected value
on_value_changed function
change callback, will receive the selected value
options any[]
array of selectable options
to_string function
function that converts an item to a string (or a localization message); defaults to tostring
issue table
issue related to the input; table with the following keys (all required):
severity string
either editor.ui.ISSUE_SEVERITY.WARNING or editor.ui.ISSUE_SEVERITY.ERROR
message string, message
issue message that will be shown in a tooltip; either a string or a localization message
tooltip string, message
tooltip message shown on hover; either a string or a localization message
enabled boolean
determines if the input component can be interacted with
alignment string
alignment of the component content within its assigned bounds, defaults to editor.ui.ALIGNMENT.TOP_LEFT; either:
  • editor.ui.ALIGNMENT.TOP_LEFT
  • editor.ui.ALIGNMENT.TOP
  • editor.ui.ALIGNMENT.TOP_RIGHT
  • editor.ui.ALIGNMENT.LEFT
  • editor.ui.ALIGNMENT.CENTER
  • editor.ui.ALIGNMENT.RIGHT
  • editor.ui.ALIGNMENT.BOTTOM_LEFT
  • editor.ui.ALIGNMENT.BOTTOM
  • editor.ui.ALIGNMENT.BOTTOM_RIGHT
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.ui.separator *Type:* FUNCTION Thin line for visual content separation, by default horizontal and aligned to center **Parameters** - `props` (table) - Optional props:
orientation string
separator line orientation, editor.ui.ORIENTATION.VERTICAL or editor.ui.ORIENTATION.HORIZONTAL; either:
  • editor.ui.ORIENTATION.VERTICAL
  • editor.ui.ORIENTATION.HORIZONTAL
alignment string
alignment of the component content within its assigned bounds, defaults to editor.ui.ALIGNMENT.TOP_LEFT; either:
  • editor.ui.ALIGNMENT.TOP_LEFT
  • editor.ui.ALIGNMENT.TOP
  • editor.ui.ALIGNMENT.TOP_RIGHT
  • editor.ui.ALIGNMENT.LEFT
  • editor.ui.ALIGNMENT.CENTER
  • editor.ui.ALIGNMENT.RIGHT
  • editor.ui.ALIGNMENT.BOTTOM_LEFT
  • editor.ui.ALIGNMENT.BOTTOM
  • editor.ui.ALIGNMENT.BOTTOM_RIGHT
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.ui.show_dialog *Type:* FUNCTION Show a modal dialog and await a result **Parameters** - `dialog` (component) - a component that resolves to editor.ui.dialog(...) **Returns** - `value` (any) - dialog result, the value used as a result prop in a editor.ui.dialog_button({...}) selected by the user, or nil if the dialog was closed and there was no cancel = true dialog button with result prop set ### editor.ui.show_external_directory_dialog *Type:* FUNCTION Show a modal OS directory selection dialog and await a result **Parameters** - `opts` (table) (optional) -
path string
initial file or directory path used by the dialog; resolved against project root if relative
title string, message
OS window title, either a string or a localization message
**Returns** - `value` (string | nil) - either absolute directory path or nil if user canceled directory selection ### editor.ui.show_external_file_dialog *Type:* FUNCTION Show a modal OS file selection dialog and await a result **Parameters** - `opts` (table) (optional) -
path string
initial file or directory path used by the dialog; resolved against project root if relative
title string, message
OS window title, either a string or a localization message
filters table[]
File filters, an array of filter tables, where each filter has following keys:
description string, message
text explaining the filter, either a literal string like "Text files (*.txt)" or a localization message
extensions string[]
array of file extension patterns, e.g. "*.txt", "*.*" or "game.project"
**Returns** - `value` (string | nil) - either absolute file path or nil if user canceled file selection ### editor.ui.show_resource_dialog *Type:* FUNCTION Show a modal resource selection dialog and await a result **Parameters** - `opts` (table) (optional) -
extensions string[]
if specified, restricts selectable resources in the dialog to specified file extensions; e.g. {"collection", "go"}
selection string
either "single" or "multiple", defaults to "single"
title string, message
dialog title, either a string or a localization message, defaults to localization.message("dialog.select-resource.title")
**Returns** - `value` (string | string[) - |nil] if user made no selection, returns nil. Otherwise, if selection mode is "single", returns selected resource path; otherwise returns a non-empty array of selected resource paths. ### editor.ui.SPACING.LARGE *Type:* VARIABLE "large" ### editor.ui.SPACING.MEDIUM *Type:* VARIABLE "medium" ### editor.ui.SPACING.NONE *Type:* VARIABLE "none" ### editor.ui.SPACING.SMALL *Type:* VARIABLE "small" ### editor.ui.string_field *Type:* FUNCTION String input component based on a text field, reports changes on commit (Enter or focus loss) **Parameters** - `props` (table) - Optional props:
value any
value
on_value_changed function
value change callback, will receive the new value
issue table
issue related to the input; table with the following keys (all required):
severity string
either editor.ui.ISSUE_SEVERITY.WARNING or editor.ui.ISSUE_SEVERITY.ERROR
message string, message
issue message that will be shown in a tooltip; either a string or a localization message
tooltip string, message
tooltip message shown on hover; either a string or a localization message
enabled boolean
determines if the input component can be interacted with
alignment string
alignment of the component content within its assigned bounds, defaults to editor.ui.ALIGNMENT.TOP_LEFT; either:
  • editor.ui.ALIGNMENT.TOP_LEFT
  • editor.ui.ALIGNMENT.TOP
  • editor.ui.ALIGNMENT.TOP_RIGHT
  • editor.ui.ALIGNMENT.LEFT
  • editor.ui.ALIGNMENT.CENTER
  • editor.ui.ALIGNMENT.RIGHT
  • editor.ui.ALIGNMENT.BOTTOM_LEFT
  • editor.ui.ALIGNMENT.BOTTOM
  • editor.ui.ALIGNMENT.BOTTOM_RIGHT
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.ui.TEXT_ALIGNMENT.CENTER *Type:* VARIABLE "center" ### editor.ui.TEXT_ALIGNMENT.JUSTIFY *Type:* VARIABLE "justify" ### editor.ui.TEXT_ALIGNMENT.LEFT *Type:* VARIABLE "left" ### editor.ui.TEXT_ALIGNMENT.RIGHT *Type:* VARIABLE "right" ### editor.ui.use_memo *Type:* FUNCTION A hook that caches the result of a computation between re-renders. See editor.ui.component for hooks caveats and rules. If any of the arguments to use_memo change during a component refresh (checked with ==), the value will be recomputed. **Parameters** - `compute` (function) - function that will be used to compute the cached value - `...` (...any) (optional) - args to the computation function **Returns** - `values` (...any) - all returned values of the compute function **Examples** ``` local function increment(n) return n + 1 end local function make_listener(set_count) return function() set_count(increment) end end local counter_button = editor.ui.component(function(props) local count, set_count = editor.ui.use_state(props.count) local on_pressed = editor.ui.use_memo(make_listener, set_count) return editor.ui.text_button { text = tostring(count), on_pressed = on_pressed } end) ``` ### editor.ui.use_state *Type:* FUNCTION A hook that adds local state to the component. See editor.ui.component for hooks caveats and rules. If any of the arguments to use_state change during a component refresh (checked with ==), the current state will be reset to the initial one. **Parameters** - `init` (any | function) - local state initializer, either initial data structure or function that produces the data structure - `...` (...any) (optional) - used when init is a function, the args are passed to the initializer function **Returns** - `state` (any) - current local state, starts with initial state, then may be changed using the returned set_state function - `set_state` (function) - function that changes the local state and causes the component to refresh. The function may be used in 2 ways:
  • to set the state to some other data structure: pass the data structure as a value
  • to replace the state using updater function: pass a function to set_state — it will be invoked with the current state, as well as with the rest of the arguments passed to set_state after the updater function. The state will be set to the value returned from the updater function
**Examples** ``` local function increment(n) return n + 1 end local counter_button = editor.ui.component(function(props) local count, set_count = editor.ui.use_state(props.count) return editor.ui.text_button { text = tostring(count), on_pressed = function() set_count(increment) end } end) ``` ### editor.ui.vertical *Type:* FUNCTION Layout container that places its children in a vertical column one after another **Parameters** - `props` (table) - Optional props:
children component[]
array of child components
padding string, number
empty space from the edges of the container to its children; either:
  • editor.ui.PADDING.NONE
  • editor.ui.PADDING.SMALL
  • editor.ui.PADDING.MEDIUM
  • editor.ui.PADDING.LARGE
  • non-negative number, pixels
spacing string, number
empty space between child components, defaults to editor.ui.SPACING.MEDIUM; either:
  • editor.ui.SPACING.NONE
  • editor.ui.SPACING.SMALL
  • editor.ui.SPACING.MEDIUM
  • editor.ui.SPACING.LARGE
  • non-negative number, pixels
alignment string
alignment of the component content within its assigned bounds, defaults to editor.ui.ALIGNMENT.TOP_LEFT; either:
  • editor.ui.ALIGNMENT.TOP_LEFT
  • editor.ui.ALIGNMENT.TOP
  • editor.ui.ALIGNMENT.TOP_RIGHT
  • editor.ui.ALIGNMENT.LEFT
  • editor.ui.ALIGNMENT.CENTER
  • editor.ui.ALIGNMENT.RIGHT
  • editor.ui.ALIGNMENT.BOTTOM_LEFT
  • editor.ui.ALIGNMENT.BOTTOM
  • editor.ui.ALIGNMENT.BOTTOM_RIGHT
grow boolean
determines if the component should grow to fill available space in a horizontal or vertical layout container
row_span integer
how many rows the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
column_span integer
how many columns the component spans inside a grid container, must be positive. This prop is only useful for components inside a grid container.
**Returns** - `value` (component) - UI component ### editor.version *Type:* VARIABLE A string, version name of Defold ### http.request *Type:* FUNCTION Perform an HTTP request **Parameters** - `url` (string) - request URL - `opts` (table) (optional) - Additional request options, a table with the following keys:
method string
request method, defaults to "GET"
headers table
request headers, a table with string keys and values
body string
request body
as string
response body converter, either "string" or "json"
**Returns** - `response` (table) - HTTP response, a table with the following keys:
status integer
response code
headers table
response headers, a table where each key is a lower-cased string, and each value is either a string or an array of strings if the header was repeated
body string, any, nil
response body, present only when as option was provided, either a string or a parsed json value
### http.server.external_file_response *Type:* FUNCTION Create HTTP response that will stream the content of a file defined by the path **Parameters** - `path` (string) - External file path, resolved against project root if relative - `status` (integer) (optional) - HTTP status code, an integer, default 200 - `headers` (table<string,string>) (optional) - HTTP response headers, a table from lower-case header names to header values **Returns** - `response` (response) - HTTP response value, userdata ### http.server.json_response *Type:* FUNCTION Create HTTP response with a JSON value **Parameters** - `value` (any) - Any Lua value that may be represented as JSON - `status` (integer) (optional) - HTTP status code, an integer, default 200 - `headers` (table<string,string>) (optional) - HTTP response headers, a table from lower-case header names to header values **Returns** - `response` (response) - HTTP response value, userdata ### http.server.local_url *Type:* VARIABLE Editor's HTTP server local url ### http.server.port *Type:* VARIABLE Editor's HTTP server port ### http.server.resource_response *Type:* FUNCTION Create HTTP response that will stream the content of a resource defined by the resource path **Parameters** - `resource_path` (string) - Resource path (starting with /) - `status` (integer) (optional) - HTTP status code, an integer, default 200 - `headers` (table<string,string>) (optional) - HTTP response headers, a table from lower-case header names to header values **Returns** - `response` (response) - HTTP response value, userdata ### http.server.response *Type:* FUNCTION Create HTTP response **Parameters** - `status` (integer) (optional) - HTTP status code, an integer, default 200 - `headers` (table<string,string>) (optional) - HTTP response headers, a table from lower-case header names to header values - `body` (string) (optional) - HTTP response body **Returns** - `response` (response) - HTTP response value, userdata ### http.server.route *Type:* FUNCTION Create route definition for the editor's HTTP server **Parameters** - `path` (string) - HTTP URI path, starts with /; may include path patterns ({name} for a single segment and {*name} for the rest of the request path) that will be extracted from the path and provided to the handler as a part of the request - `method` (string) (optional) - HTTP request method, default "GET" - `as` (string) (optional) - Request body converter, either "string" or "json"; the body will be discarded if not specified - `openapi` (table) (optional) - Optional OpenAPI Operation Object for this route method, exposed from /openapi.json. Must follow https://spec.openapis.org/oas/v3.0.3.html#operation-object. - `handler` (function) - Request handler function, will receive request argument, a table with the following keys:
path string
full matched path, a string starting with /
method string
HTTP request method, e.g. "POST"
headers table<string,(string|string[])>
HTTP request headers, a table from lower-case header names to header values
query string
optional query string
body string, any
optional request body, depends on the as argument
Handler function should return either a single response value, or 0 or more arguments to the http.server.response() function **Returns** - `route` (route) - HTTP server route **Examples** Receive JSON and respond with JSON: ``` http.server.route( "/json", "POST", "json", function(request) pprint(request.body) return 200 end ) ``` Extract parts of the path: ``` http.server.route( "/users/{user}/orders", function(request) print(request.user) end ) ``` Simple file server: ``` http.server.route( "/files/{*file}", function(request) local attrs = editor.external_file_attributes(request.file) if attrs.is_file then return http.server.external_file_response(request.file) elseif attrs.is_directory then return 400 else return 404 end end ) ``` ### http.server.url *Type:* VARIABLE Editor's HTTP server url ### json.decode *Type:* FUNCTION Decode JSON string to Lua value **Parameters** - `json` (string) - json data - `options` (table) (optional) - A table with the following keys:
all boolean
if true, decodes all json values in a string and returns an array
### json.encode *Type:* FUNCTION Encode Lua value to JSON string **Parameters** - `value` (any) - any Lua value that may be represented as JSON ### localization.and_list *Type:* FUNCTION Create a message pattern that renders a list with the "and" conjunction (for example: a, b, and c) once it is stringified **Parameters** - `items` (any[) - ] array of values; each value may be nil, boolean, number, string, or another message instance **Returns** - `message` (message) - a userdata value that, when stringified with tostring(), will produce a localized text according to the currently selected language in the editor ### localization.concat *Type:* FUNCTION Create a message pattern that concatenates values (similar to table.concat) and performs the actual concatenation when stringified **Parameters** - `items` (any[) - ] array of values; each value may be nil, boolean, number, string, or another message instance - `separator` (nil | boolean | number | string | message) (optional) - optional separator inserted between values; defaults to an empty string **Returns** - `message` (message) - a userdata value that, when stringified with tostring(), will produce a localized text according to the currently selected language in the editor ### localization.message *Type:* FUNCTION Create a message pattern for a localization key defined in an .editor_localization file; the actual localization happens when the returned value is stringified **Parameters** - `key` (string) - localization key defined in an .editor_localization file - `vars` (table) (optional) - optional table with variables to be substituted in the localized string that uses ICU Message Format syntax; keys must be strings; values must be either nil, boolean, number, string, or another message instance **Returns** - `message` (message) - a userdata value that, when stringified with tostring(), will produce a localized text according to the currently selected language in the editor ### localization.or_list *Type:* FUNCTION Create a message pattern that renders a list with the "or" conjunction (for example: a, b, or c) once it is stringified **Parameters** - `items` (any[) - ] array of values; each value may be nil, boolean, number, string, or another message instance **Returns** - `message` (message) - a userdata value that, when stringified with tostring(), will produce a localized text according to the currently selected language in the editor ### pprint *Type:* FUNCTION Pretty-print a Lua value **Parameters** - `value` (any) - any Lua value to pretty-print ### tilemap.tiles.clear *Type:* FUNCTION Remove all tiles **Parameters** - `tiles` (tiles) - unbounded 2d grid of tiles **Returns** - `tiles` (tiles) - unbounded 2d grid of tiles ### tilemap.tiles.get_info *Type:* FUNCTION Get full information from a tile at a particular coordinate **Parameters** - `tiles` (tiles) - unbounded 2d grid of tiles - `x` (integer) - x coordinate of a tile - `y` (integer) - y coordinate of a tile **Returns** - `info` (table) - full tile information table with the following keys:
index integer
1-indexed tile index of a tilemap's tilesource
h_flip boolean
horizontal flip
v_flip boolean
vertical flip
rotate_90 boolean
whether the tile is rotated 90 degrees clockwise
### tilemap.tiles.get_tile *Type:* FUNCTION Get a tile index at a particular coordinate **Parameters** - `tiles` (tiles) - unbounded 2d grid of tiles - `x` (integer) - x coordinate of a tile - `y` (integer) - y coordinate of a tile **Returns** - `tile_index` (integer) - 1-indexed tile index of a tilemap's tilesource ### tilemap.tiles.iterator *Type:* FUNCTION Create an iterator over all tiles in a tiles data structure When iterating using for loop, each iteration returns x, y and tile index of a tile in a tile map **Parameters** - `tiles` (tiles) - unbounded 2d grid of tiles **Returns** - `iter` (function) - iterator **Examples** Iterate over all tiles in a tile map: ``` local layers = editor.get("/level.tilemap", "layers") for i = 1, #layers do local tiles = editor.get(layers[i], "tiles") for x, y, i in tilemap.tiles.iterator(tiles) do print(x, y, i) end end ``` ### tilemap.tiles.new *Type:* FUNCTION Create a new unbounded 2d grid data structure for storing tilemap layer tiles **Returns** - `tiles` (tiles) - unbounded 2d grid of tiles ### tilemap.tiles.remove *Type:* FUNCTION Remove a tile at a particular coordinate **Parameters** - `tiles` (tiles) - unbounded 2d grid of tiles - `x` (integer) - x coordinate of a tile - `y` (integer) - y coordinate of a tile **Returns** - `tiles` (tiles) - unbounded 2d grid of tiles ### tilemap.tiles.set *Type:* FUNCTION Set a tile at a particular coordinate **Parameters** - `tiles` (tiles) - unbounded 2d grid of tiles - `x` (integer) - x coordinate of a tile - `y` (integer) - y coordinate of a tile - `tile_or_info` (integer | table) - Either 1-indexed tile index of a tilemap's tilesource or full tile information table with the following keys:
index integer
1-indexed tile index of a tilemap's tilesource
h_flip boolean
horizontal flip
v_flip boolean
vertical flip
rotate_90 boolean
whether the tile is rotated 90 degrees clockwise
**Returns** - `tiles` (tiles) - unbounded 2d grid of tiles ### zip.METHOD.DEFLATED *Type:* VARIABLE "deflated" compression method ### zip.METHOD.STORED *Type:* VARIABLE "stored" compression method, i.e. no compression ### zip.ON_CONFLICT.ERROR *Type:* VARIABLE "error", any conflict aborts extraction ### zip.ON_CONFLICT.OVERWRITE *Type:* VARIABLE "skip", existing file is overwritten ### zip.ON_CONFLICT.SKIP *Type:* VARIABLE "skip", existing file is preserved ### zip.pack *Type:* FUNCTION Create a ZIP archive **Parameters** - `output_path` (string) - output zip file path, resolved against project root if relative - `opts` (table) (optional) - compression options, a table with the following keys:
method string
compression method, either zip.METHOD.DEFLATED (default) or zip.METHOD.STORED
level integer
compression level, an integer between 0 and 9, only useful when the compression method is zip.METHOD.DEFLATED; defaults to 6
- `entries` (string | table) - entries to compress, either a string (relative path to file or folder to include) or a table with the following keys:
1 string
required; source file or folder path to include, resolved against project root if relative
2 string
optional; target file or folder path in the zip archive. May be omitted if source is a relative path that does not go above the project directory.
method string
compression method, either zip.METHOD.DEFLATED (default) or zip.METHOD.STORED
level integer
compression level, an integer between 0 and 9, only useful when the compression method is zip.METHOD.DEFLATED; defaults to 6
**Examples** Archive a file and a folder: ``` zip.pack("build.zip", {"build", "game.project"}) ``` Change the location of the files within the archive: ``` zip.pack("build.zip", { {"build/wasm-web", "."}, {"configs/prod.json", "config.json"} }) ``` Create archive without compression (much faster to create the archive, bigger archive file size, allows mmap access): ``` zip.pack("build.zip", {method = zip.METHOD.STORED}, { "build", "resources" }) ``` Don't compress one of the folders: ``` zip.pack("build.zip", { {"assets", method = zip.METHOD.STORED}, "build/wasm-web" }) ``` Include files from outside the project: ``` zip.pack("build.zip", { "build", {"../secrets/auth-key.txt", "auth-key.txt"} }) ``` ### zip.unpack *Type:* FUNCTION Extract a ZIP archive **Parameters** - `archive_path` (string) - zip file path, resolved against project root if relative - `target_path` (string) (optional) - target path for extraction, defaults to parent of archive_path if omitted - `opts` (table) (optional) - extraction options, a table with the following keys:
on_conflict string
conflict resolution strategy, defaults to zip.ON_CONFLICT.ERROR
- `paths` (table) (optional) - entries to extract, relative string paths **Examples** Extract everything to a build dir: ``` zip.unpack("build/dev/resources.zip") ``` Extract to a different directory: ``` zip.unpack( "build/dev/resources.zip", "build/dev/tmp", ) ``` Extract while overwriting existing files on conflict: ``` zip.unpack( "build/dev/resources.zip", {on_conflict = zip.ON_CONFLICT.OVERWRITE} ) ``` Extract a single file: ``` zip.unpack( "build/dev/resources.zip", {"config.json"} ) ``` ### zlib.deflate *Type:* FUNCTION Deflate (compress) a buffer **Parameters** - `buf` (string) - buffer to deflate **Returns** - `buf` (string) - deflated buffer ### zlib.inflate *Type:* FUNCTION Inflate (decompress) a buffer **Parameters** - `buf` (string) - buffer to inflate **Returns** - `buf` (string) - inflated buffer # Factory {#apis:factory-lua} **Namespace:** `factory` **Language:** Lua **Type:** Defold Lua **File:** `script_factory.cpp` **Source:** `engine/gamesys/src/gamesys/scripts/script_factory.cpp` Functions for controlling factory components which are used to dynamically spawn game objects into the runtime. ## API ### factory.create *Type:* FUNCTION The URL identifies which factory should create the game object. If the game object is created inside of the frame (e.g. from an update callback), the game object will be created instantly, but none of its component will be updated in the same frame. Properties defined in scripts in the created game object can be overridden through the properties-parameter below. See go.property for more information on script properties. Calling factory.create on a factory that is marked as dynamic without having loaded resources using factory.load will synchronously load and create resources which may affect application performance. **Parameters** - `url` (string | hash | url) - the factory that should create a game object. - `position` (vector3) (optional) - the position of the new game object, the position of the game object calling factory.create() is used by default, or if the value is nil. - `rotation` (quaternion) (optional) - the rotation of the new game object, the rotation of the game object calling factory.create() is used by default, or if the value is nil. - `properties` (table) (optional) - the properties defined in a script attached to the new game object. - `scale` (number | vector3) (optional) - the scale of the new game object (must be greater than 0), the scale of the game object containing the factory is used by default, or if the value is nil **Returns** - `id` (hash) - the global id of the spawned game object **Examples** How to create a new game object: ``` function init(self) -- create a new game object and provide property values self.my_created_object = factory.create("#factory", nil, nil, {my_value = 1}) -- communicate with the object msg.post(self.my_created_object, "hello") end ``` And then let the new game object have a script attached: ``` go.property("my_value", 0) function init(self) -- do something with self.my_value which is now one end ``` ### factory.get_status *Type:* FUNCTION This returns status of the factory. Calling this function when the factory is not marked as dynamic loading always returns factory.STATUS_LOADED. **Parameters** - `url` (string | hash | url) (optional) - the factory component to get status from **Returns** - `status` (constant) - status of the factory component
  • factory.STATUS_UNLOADED
  • factory.STATUS_LOADING
  • factory.STATUS_LOADED
### factory.load *Type:* FUNCTION Resources are referenced by the factory component until the existing (parent) collection is destroyed or factory.unload is called. Calling this function when the factory is not marked as dynamic loading does nothing. **Parameters** - `url` (string | hash | url) (optional) - the factory component to load - `complete_function` (function(self, url, result)) (optional) - function to call when resources are loaded.
self
object The current object.
url
url url of the factory component
result
boolean True if resources were loaded successfully
**Examples** How to load resources of a factory prototype. ``` factory.load("#factory", function(self, url, result) end) ``` ### factory.set_prototype *Type:* FUNCTION Changes the prototype for the factory. **Notes** - - Requires the factory to have the "Dynamic Prototype" set - Cannot be set when the state is COMP_FACTORY_STATUS_LOADING - Setting the prototype to `nil` will revert back to the original prototype. **Parameters** - `url` (string | hash | url) (optional) - the factory component - `prototype` (string | nil) (optional) - the path to the new prototype, or nil **Examples** How to unload the previous prototypes resources, and then spawn a new game object ``` factory.unload("#factory") -- unload the previous resources factory.set_prototype("#factory", "/main/levels/enemyA.goc") local id = factory.create("#factory", go.get_world_position(), vmath.quat()) ``` ### factory.STATUS_LOADED *Type:* CONSTANT loaded ### factory.STATUS_LOADING *Type:* CONSTANT loading ### factory.STATUS_UNLOADED *Type:* CONSTANT unloaded ### factory.unload *Type:* FUNCTION This decreases the reference count for each resource loaded with factory.load. If reference is zero, the resource is destroyed. Calling this function when the factory is not marked as dynamic loading does nothing. **Parameters** - `url` (string | hash | url) (optional) - the factory component to unload **Examples** How to unload resources of a factory prototype loaded with factory.load ``` factory.unload("#factory") ``` # Font {#apis:font-lua} **Namespace:** `font` **Language:** Lua **Type:** Defold Lua **File:** `script_font.cpp` **Source:** `engine/gamesys/src/gamesys/scripts/script_font.cpp` Functions, messages and properties used to manipulate font resources. ## API ### font.add_font *Type:* FUNCTION associates a ttf resource to a .fontc file. **Notes** - The ttf font is loaded via the resource system. There are a few ways it can be accessed: - It was already loaded in the resource system - It is bundled via our game data - It is accessible via a live update mount - The reference count will increase for the .ttf font **Parameters** - `fontc` (string | hash) - The path to the .fontc resource - `ttf` (string | hash) - The path to the .ttf resource **Examples** ``` local font_hash = hash("/assets/fonts/roboto.fontc") local ttf_hash = hash("/assets/fonts/Roboto/Roboto-Bold.ttf") font.add_font(font_hash, ttf_hash) ``` ### font.get_info *Type:* FUNCTION Gets information about a font, such as the associated font files **Parameters** - `fontc` (string | hash) - The path to the .fontc resource **Returns** - `info` (table) - the information table contains these fields:
path
hash The path hash of the current file.
fonts
table An array of associated font (e.g. .ttf) files. Each item is a table that contains:
path
string The path of the font file
path_hash
hash The path of the font file
### font.prewarm_text *Type:* FUNCTION prepopulates the font glyph cache with rasterised glyphs **Parameters** - `fontc` (string | hash) - The path to the .fontc resource - `text` (string) - The text to layout - `callback` (function(self, request_id, result, errstring)) (optional) - (optional) A callback function that is called after the request is finished
self
object The current object.
request_id
number The request id
result
boolean True if request was succesful
errstring
string nil if the request was successful
**Returns** - `request_id` (number) - Returns the asynchronous request id **Examples** ``` local font_hash = hash("/assets/fonts/roboto.fontc") font.prewarm_text(font_hash, "Some text", function (self, request_id, result, errstring) -- cache is warm, show the text! end) ``` ### font.remove_font *Type:* FUNCTION associates a ttf resource to a .fontc file **Notes** - The reference count will decrease for the .ttf font **Parameters** - `fontc` (string | hash) - The path to the .fontc resource - `ttf` (string | hash) - The path to the .ttf resource **Examples** ``` local font_hash = hash("/assets/fonts/roboto.fontc") local ttf_hash = hash("/assets/fonts/Roboto/Roboto-Bold.ttf") font.remove_font(font_hash, ttf_hash) ``` # Game object {#apis:go-lua} **Namespace:** `go` **Language:** Lua **Type:** Defold Lua **File:** `gameobject_ddf.proto` **Source:** `engine/gameobject/proto/gameobject/gameobject_ddf.proto` Game object API documentation ## API ### acquire_input_focus *Type:* MESSAGE Post this message to a game object instance to make that instance acquire the user input focus. User input is distributed by the engine to every instance that has requested it. The last instance to request focus will receive it first. This means that the scripts in the instance will have first-hand-chance at reacting on user input, possibly consuming it (by returning true from on_input) so that no other instances can react on it. The most common case is for a script to send this message to itself when it needs to respond to user input. A script belonging to an instance which has the user input focus will receive the input actions in its on_input callback function. See on_input for more information on how user input can be handled. **Examples** This example demonstrates how to acquire and act on user input. ``` function init(self) -- acquire input focus as soon as the instance has been initialized msg.post(".", "acquire_input_focus") end function on_input(self, action_id, action) -- check which input we received if action_id == hash("my_action") then -- act on the input self.my_action_amount = action.value end end ``` ### disable *Type:* MESSAGE This message disables the receiving component. All components are enabled by default, which means they will receive input, updates and be a part of the simulation. A component is disabled when it receives the disable message. Components that currently supports this message are: Camera Collection Proxy Collision Object Gui Label Spine Model Sprite Tile Grid Model Mesh **Examples** Disable the component "my_component": ``` msg.post("#my_component", "disable") ``` ### enable *Type:* MESSAGE This message enables the receiving component. All components are enabled by default, which means they will receive input, updates and be a part of the simulation. A component is disabled when it receives the disable message. Components that currently supports this message are: Camera Collection Proxy Collision Object Gui Label Spine Model Sprite Tile Grid Model Mesh **Examples** Enable the component "my_component": ``` msg.post("#my_component", "enable") ``` ### euler *Type:* PROPERTY The rotation of the game object expressed in Euler angles. Euler angles are specified in degrees in the interval (-360, 360). The type of the property is vector3. **Examples** How to set a game object's rotation with euler angles, either as a vector3 or selecting a specific dimension: ``` function init(self) -- set "player" euler z rotation component to 45 degrees around z. local rotz = 45 go.set("player", "euler.z", rotz) local rot = go.get("player", "euler") -- do something useful assert(rot.z == rotz) end ``` ### final *Type:* FUNCTION This is a callback-function, which is called by the engine when a script component is finalized (destroyed). It can be used to e.g. take some last action, report the finalization to other game object instances, delete spawned objects or release user input focus (see release_input_focus). **Parameters** - `self` (userdata) - reference to the script state to be used for storing data **Examples** ``` function final(self) -- report finalization msg.post("my_friend_instance", "im_dead", {my_stats = self.some_value}) end ``` ### fixed_update *Type:* FUNCTION This is a callback-function, which is called by the engine at fixed intervals to update the state of a script component. The function will be called if 'Fixed Update Frequency' is enabled in the Engine section of game.project. It can for instance be used to update game logic with the physics simulation if using a fixed timestep for the physics (enabled by ticking 'Use Fixed Timestep' in the Physics section of game.project). **Parameters** - `self` (userdata) - reference to the script state to be used for storing data - `dt` (number) - the time-step of the frame update ### go.animate *Type:* FUNCTION This is only supported for numerical properties. If the node property is already being animated, that animation will be canceled and replaced by the new one. If a complete_function (lua function) is specified, that function will be called when the animation has completed. By starting a new animation in that function, several animations can be sequenced together. See the examples for more information. If you call go.animate() from a game object's final() function, any passed complete_function will be ignored and never called upon animation completion. See the properties guide for which properties can be animated and the animation guide for how them. **Parameters** - `url` (string | hash | url) - url of the game object or component having the property - `property` (string | hash) - id of the property to animate - `playback` (go.PLAYBACK_ONCE_FORWARD | go.PLAYBACK_ONCE_BACKWARD | go.PLAYBACK_ONCE_PINGPONG | go.PLAYBACK_LOOP_FORWARD | go.PLAYBACK_LOOP_BACKWARD | go.PLAYBACK_LOOP_PINGPONG) - playback mode of the animation
  • go.PLAYBACK_ONCE_FORWARD
  • go.PLAYBACK_ONCE_BACKWARD
  • go.PLAYBACK_ONCE_PINGPONG
  • go.PLAYBACK_LOOP_FORWARD
  • go.PLAYBACK_LOOP_BACKWARD
  • go.PLAYBACK_LOOP_PINGPONG
- `to` (number | vector3 | vector4 | quaternion) - target property value - `easing` (vector | go.EASING_INBACK | go.EASING_INBOUNCE | go.EASING_INCIRC | go.EASING_INCUBIC | go.EASING_INELASTIC | go.EASING_INEXPO | go.EASING_INOUTBACK | go.EASING_INOUTBOUNCE | go.EASING_INOUTCIRC | go.EASING_INOUTCUBIC | go.EASING_INOUTELASTIC | go.EASING_INOUTEXPO | go.EASING_INOUTQUAD | go.EASING_INOUTQUART | go.EASING_INOUTQUINT | go.EASING_INOUTSINE | go.EASING_INQUAD | go.EASING_INQUART | go.EASING_INQUINT | go.EASING_INSINE | go.EASING_LINEAR | go.EASING_OUTBACK | go.EASING_OUTBOUNCE | go.EASING_OUTCIRC | go.EASING_OUTCUBIC | go.EASING_OUTELASTIC | go.EASING_OUTEXPO | go.EASING_OUTINBACK | go.EASING_OUTINBOUNCE | go.EASING_OUTINCIRC | go.EASING_OUTINCUBIC | go.EASING_OUTINELASTIC | go.EASING_OUTINEXPO | go.EASING_OUTINQUAD | go.EASING_OUTINQUART | go.EASING_OUTINQUINT | go.EASING_OUTINSINE | go.EASING_OUTQUAD | go.EASING_OUTQUART | go.EASING_OUTQUINT | go.EASING_OUTSINE) - easing to use during animation. Either specify a constant, see the animation guide for a complete list, or a vmath.vector with a curve - `duration` (number) - duration of the animation in seconds - `delay` (number) (optional) - delay before the animation starts in seconds - `complete_function` (function(self, url, property)) (optional) - optional function to call when the animation has completed
self
object The current object.
url
url The game object or component instance for which the property is animated.
property
hash The id of the animated property.
**Examples** Animate the position of a game object to x = 10 during 1 second, then y = 20 during 1 second: ``` local function x_done(self, url, property) go.animate(go.get_id(), "position.y", go.PLAYBACK_ONCE_FORWARD, 20, go.EASING_LINEAR, 1) end function init(self) go.animate(go.get_id(), "position.x", go.PLAYBACK_ONCE_FORWARD, 10, go.EASING_LINEAR, 1, 0, x_done) end ``` Animate the y position of a game object using a crazy custom easing curve: ``` local values = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 } local vec = vmath.vector(values) go.animate("go", "position.y", go.PLAYBACK_LOOP_PINGPONG, 100, vec, 2.0) ``` ### go.cancel_animations *Type:* FUNCTION By calling this function, all or specified stored property animations of the game object or component will be canceled. See the properties guide for which properties can be animated and the animation guide for how to animate them. **Parameters** - `url` (string | hash | url) - url of the game object or component - `property` (string | hash) (optional) - optional id of the property to cancel **Examples** Cancel the animation of the position of a game object: ``` go.cancel_animations(go.get_id(), "position") ``` Cancel all property animations of the current game object: ``` go.cancel_animations(".") ``` Cancel all property animations of the sprite component of the current game object: ``` go.cancel_animations("#sprite") ``` ### go.delete *Type:* FUNCTION Delete one or more game objects identified by id. Deletion is asynchronous meaning that the game object(s) are scheduled for deletion which will happen at the end of the current frame. Note that game objects scheduled for deletion will be counted against max_instances in "game.project" until they are actually removed. Deleting a game object containing a particle FX component emitting particles will not immediately stop the particle FX from emitting particles. You need to manually stop the particle FX using particlefx.stop(). Deleting a game object containing a sound component that is playing will not immediately stop the sound from playing. You need to manually stop the sound using sound.stop(). **Parameters** - `id` (string | hash | url | table) (optional) - optional id or table of id's of the instance(s) to delete, the instance of the calling script is deleted by default - `recursive` (boolean) (optional) - optional boolean, set to true to recursively delete child hiearchy in child to parent order **Examples** This example demonstrates how to delete game objects ``` -- Delete the script game object go.delete() -- Delete a game object with the id "my_game_object". local id = go.get_id("my_game_object") -- retrieve the id of the game object to be deleted go.delete(id) -- Delete a list of game objects. local ids = { hash("/my_object_1"), hash("/my_object_2"), hash("/my_object_3") } go.delete(ids) ``` This example demonstrates how to delete a game objects and their children (child to parent order) ``` -- Delete the script game object and it's children go.delete(true) -- Delete a game object with the id "my_game_object" and it's children. local id = go.get_id("my_game_object") -- retrieve the id of the game object to be deleted go.delete(id, true) -- Delete a list of game objects and their children. local ids = { hash("/my_object_1"), hash("/my_object_2"), hash("/my_object_3") } go.delete(ids, true) ``` ### go.EASING_INBACK *Type:* CONSTANT in-back ### go.EASING_INBOUNCE *Type:* CONSTANT in-bounce ### go.EASING_INCIRC *Type:* CONSTANT in-circlic ### go.EASING_INCUBIC *Type:* CONSTANT in-cubic ### go.EASING_INELASTIC *Type:* CONSTANT in-elastic ### go.EASING_INEXPO *Type:* CONSTANT in-exponential ### go.EASING_INOUTBACK *Type:* CONSTANT in-out-back ### go.EASING_INOUTBOUNCE *Type:* CONSTANT in-out-bounce ### go.EASING_INOUTCIRC *Type:* CONSTANT in-out-circlic ### go.EASING_INOUTCUBIC *Type:* CONSTANT in-out-cubic ### go.EASING_INOUTELASTIC *Type:* CONSTANT in-out-elastic ### go.EASING_INOUTEXPO *Type:* CONSTANT in-out-exponential ### go.EASING_INOUTQUAD *Type:* CONSTANT in-out-quadratic ### go.EASING_INOUTQUART *Type:* CONSTANT in-out-quartic ### go.EASING_INOUTQUINT *Type:* CONSTANT in-out-quintic ### go.EASING_INOUTSINE *Type:* CONSTANT in-out-sine ### go.EASING_INQUAD *Type:* CONSTANT in-quadratic ### go.EASING_INQUART *Type:* CONSTANT in-quartic ### go.EASING_INQUINT *Type:* CONSTANT in-quintic ### go.EASING_INSINE *Type:* CONSTANT in-sine ### go.EASING_LINEAR *Type:* CONSTANT linear interpolation ### go.EASING_OUTBACK *Type:* CONSTANT out-back ### go.EASING_OUTBOUNCE *Type:* CONSTANT out-bounce ### go.EASING_OUTCIRC *Type:* CONSTANT out-circlic ### go.EASING_OUTCUBIC *Type:* CONSTANT out-cubic ### go.EASING_OUTELASTIC *Type:* CONSTANT out-elastic ### go.EASING_OUTEXPO *Type:* CONSTANT out-exponential ### go.EASING_OUTINBACK *Type:* CONSTANT out-in-back ### go.EASING_OUTINBOUNCE *Type:* CONSTANT out-in-bounce ### go.EASING_OUTINCIRC *Type:* CONSTANT out-in-circlic ### go.EASING_OUTINCUBIC *Type:* CONSTANT out-in-cubic ### go.EASING_OUTINELASTIC *Type:* CONSTANT out-in-elastic ### go.EASING_OUTINEXPO *Type:* CONSTANT out-in-exponential ### go.EASING_OUTINQUAD *Type:* CONSTANT out-in-quadratic ### go.EASING_OUTINQUART *Type:* CONSTANT out-in-quartic ### go.EASING_OUTINQUINT *Type:* CONSTANT out-in-quintic ### go.EASING_OUTINSINE *Type:* CONSTANT out-in-sine ### go.EASING_OUTQUAD *Type:* CONSTANT out-quadratic ### go.EASING_OUTQUART *Type:* CONSTANT out-quartic ### go.EASING_OUTQUINT *Type:* CONSTANT out-quintic ### go.EASING_OUTSINE *Type:* CONSTANT out-sine ### go.exists *Type:* FUNCTION This function can check for game objects in any collection by specifying the collection name in the URL. **Parameters** - `url` (string | hash | url) - url of the game object to check **Returns** - `exists` (boolean) - true if the game object exists **Examples** Check if game object "my_game_object" exists in the current collection ``` go.exists("/my_game_object") ``` Check if game object exists in another collection ``` go.exists("other_collection:/my_game_object") ``` ### go.get *Type:* FUNCTION gets a named property of the specified game object or component **Parameters** - `url` (string | hash | url) - url of the game object or component having the property - `property` (string | hash) - id of the property to retrieve - `options` (table) (optional) - optional options table - index number index into array property (1 based) - key hash name of internal property - keys table array of internal component resources identified by key (e.g. a particle fx emitter, see examples below) **Returns** - `value` (number | boolean | hash | url | vector3 | vector4 | quaternion | resource) - the value of the specified property **Examples** Get a property "speed" from a script "player", the property must be declared in the player-script: ``` go.property("speed", 50) ``` Then in the calling script (assumed to belong to the same game object, but does not have to): ``` local speed = go.get("#player", "speed") ```Get a value in a material property array ```lua -- get the first vector4 in the array: example[0] (the glsl indices are 0-based) go.get(url, "example", {index=1}) -- get the last vector4 in the array: example[15] (the glsl indices are 0-based) go.get(url, "example", {index=16}) -- get an element of a vector4 in the array: example[0].x (the glsl indices are 0-based) go.get(url, "example.x", {index=1}) ``` Getting all values in a material property array as a table ```lua -- get all vector4's in the constant array go.get(url, "example") -- result: { vector4, vector4, ... } -- get all elements of the vector4's from an array go.get(url, "example.x") -- result: { number1, number2, ... } ```Get a named property lua -- get the resource of a certain gui font local font_hash = go.get("#gui", "fonts", {key = "system_font_BIG"})Get a property from a sub-component, using the "keys" options table lua -- Addressing the first level of a component: go.get("#particlefx", "material", { keys = { "cone_emitter" } })Get a property into a deeper sub-hierarchy (if the component supports it). ```lua -- Note: There is currently no component that supports this, but a custom component could. go.get("#my_component", "some_property", { keys = { "root", "child_node" } }) ### go.get_id *Type:* FUNCTION Returns or constructs an instance identifier. The instance id is a hash of the absolute path to the instance. If path is specified, it can either be absolute or relative to the instance of the calling script. If path is not specified, the id of the game object instance the script is attached to will be returned. **Parameters** - `path` (string) (optional) - path of the instance for which to return the id **Returns** - `id` (hash) - instance id **Examples** For the instance with path /my_sub_collection/my_instance, the following calls are equivalent: ``` local id = go.get_id() -- no path, defaults to the instance containing the calling script print(id) --> hash: [/my_sub_collection/my_instance] local id = go.get_id("/my_sub_collection/my_instance") -- absolute path print(id) --> hash: [/my_sub_collection/my_instance] local id = go.get_id("my_instance") -- relative path print(id) --> hash: [/my_sub_collection/my_instance] ``` ### go.get_parent *Type:* FUNCTION Get the parent for a game object instance. **Parameters** - `id` (string | hash | url) (optional) - optional id of the game object instance to get parent for, defaults to the instance containing the calling script **Returns** - `parent_id` (hash | nil) - parent instance or nil **Examples** Get parent of the instance containing the calling script: ``` local parent_id = go.get_parent() ``` Get parent of the instance with id "x": ``` local parent_id = go.get_parent("x") ``` ### go.get_position *Type:* FUNCTION The position is relative the parent (if any). Use go.get_world_position to retrieve the global world position. **Parameters** - `id` (string | hash | url) (optional) - optional id of the game object instance to get the position for, by default the instance of the calling script **Returns** - `position` (vector3) - instance position **Replaces:** request_transform transform_response **Examples** Get the position of the game object instance the script is attached to: ``` local p = go.get_position() ``` Get the position of another game object instance "my_gameobject": ``` local pos = go.get_position("my_gameobject") ``` ### go.get_rotation *Type:* FUNCTION The rotation is relative to the parent (if any). Use go.get_world_rotation to retrieve the global world rotation. **Parameters** - `id` (string | hash | url) (optional) - optional id of the game object instance to get the rotation for, by default the instance of the calling script **Returns** - `rotation` (quaternion) - instance rotation **Examples** Get the rotation of the game object instance the script is attached to: ``` local r = go.get_rotation() ``` Get the rotation of another game object instance with id "x": ``` local r = go.get_rotation("x") ``` ### go.get_scale *Type:* FUNCTION The scale is relative the parent (if any). Use go.get_world_scale to retrieve the global world 3D scale factor. **Parameters** - `id` (string | hash | url) (optional) - optional id of the game object instance to get the scale for, by default the instance of the calling script **Returns** - `scale` (vector3) - instance scale factor **Examples** Get the scale of the game object instance the script is attached to: ``` local s = go.get_scale() ``` Get the scale of another game object instance with id "x": ``` local s = go.get_scale("x") ``` ### go.get_scale_uniform *Type:* FUNCTION The uniform scale is relative the parent (if any). If the underlying scale vector is non-uniform the min element of the vector is returned as the uniform scale factor. **Parameters** - `id` (string | hash | url) (optional) - optional id of the game object instance to get the uniform scale for, by default the instance of the calling script **Returns** - `scale` (number) - uniform instance scale factor **Examples** Get the scale of the game object instance the script is attached to: ``` local s = go.get_scale_uniform() ``` Get the uniform scale of another game object instance with id "x": ``` local s = go.get_scale_uniform("x") ``` ### go.get_world_position *Type:* FUNCTION The function will return the world position calculated at the end of the previous frame. To recalculate it within the current frame, use go.update_world_transform on the instance before calling this. Use go.get_position to retrieve the position relative to the parent. **Parameters** - `id` (string | hash | url) (optional) - optional id of the game object instance to get the world position for, by default the instance of the calling script **Returns** - `position` (vector3) - instance world position **Examples** Get the world position of the game object instance the script is attached to: ``` local p = go.get_world_position() ``` Get the world position of another game object instance with id "x": ``` local p = go.get_world_position("x") ``` ### go.get_world_rotation *Type:* FUNCTION The function will return the world rotation calculated at the end of the previous frame. To recalculate it within the current frame, use go.update_world_transform on the instance before calling this. Use go.get_rotation to retrieve the rotation relative to the parent. **Parameters** - `id` (string | hash | url) (optional) - optional id of the game object instance to get the world rotation for, by default the instance of the calling script **Returns** - `rotation` (quaternion) - instance world rotation **Examples** Get the world rotation of the game object instance the script is attached to: ``` local r = go.get_world_rotation() ``` Get the world rotation of another game object instance with id "x": ``` local r = go.get_world_rotation("x") ``` ### go.get_world_scale *Type:* FUNCTION The function will return the world 3D scale factor calculated at the end of the previous frame. To recalculate it within the current frame, use go.update_world_transform on the instance before calling this. Use go.get_scale to retrieve the 3D scale factor relative to the parent. This vector is derived by decomposing the transformation matrix and should be used with care. For most cases it should be fine to use go.get_world_scale_uniform instead. **Parameters** - `id` (string | hash | url) (optional) - optional id of the game object instance to get the world scale for, by default the instance of the calling script **Returns** - `scale` (vector3) - instance world 3D scale factor **Examples** Get the world 3D scale of the game object instance the script is attached to: ``` local s = go.get_world_scale() ``` Get the world scale of another game object instance "x": ``` local s = go.get_world_scale("x") ``` ### go.get_world_scale_uniform *Type:* FUNCTION The function will return the world scale factor calculated at the end of the previous frame. To recalculate it within the current frame, use go.update_world_transform on the instance before calling this. Use go.get_scale_uniform to retrieve the scale factor relative to the parent. **Parameters** - `id` (string | hash | url) (optional) - optional id of the game object instance to get the world scale for, by default the instance of the calling script **Returns** - `scale` (number) - instance world scale factor **Examples** Get the world scale of the game object instance the script is attached to: ``` local s = go.get_world_scale_uniform() ``` Get the world scale of another game object instance with id "x": ``` local s = go.get_world_scale_uniform("x") ``` ### go.get_world_transform *Type:* FUNCTION The function will return the world transform matrix calculated at the end of the previous frame. To recalculate it within the current frame, use go.update_world_transform on the instance before calling this. **Parameters** - `id` (string | hash | url) (optional) - optional id of the game object instance to get the world transform for, by default the instance of the calling script **Returns** - `transform` (matrix4) - instance world transform **Examples** Get the world transform of the game object instance the script is attached to: ``` local m = go.get_world_transform() ``` Get the world transform of another game object instance with id "x": ``` local m = go.get_world_transform("x") ``` ### go.PLAYBACK_LOOP_BACKWARD *Type:* CONSTANT loop backward ### go.PLAYBACK_LOOP_FORWARD *Type:* CONSTANT loop forward ### go.PLAYBACK_LOOP_PINGPONG *Type:* CONSTANT ping pong loop ### go.PLAYBACK_NONE *Type:* CONSTANT no playback ### go.PLAYBACK_ONCE_BACKWARD *Type:* CONSTANT once backward ### go.PLAYBACK_ONCE_FORWARD *Type:* CONSTANT once forward ### go.PLAYBACK_ONCE_PINGPONG *Type:* CONSTANT once ping pong ### go.property *Type:* FUNCTION This function defines a property which can then be used in the script through the self-reference. The properties defined this way are automatically exposed in the editor in game objects and collections which use the script. Note that you can only use this function outside any callback-functions like init and update. **Parameters** - `name` (string) - the id of the property - `value` (number | hash | url | vector3 | vector4 | quaternion | resource | boolean) - default value of the property. In the case of a url, only the empty constructor msg.url() is allowed. In the case of a resource one of the resource constructors (eg resource.atlas(), resource.font() etc) is expected. **Examples** This example demonstrates how to define a property called "health" in a script. The health is decreased whenever someone sends a message called "take_damage" to the script. ``` go.property("health", 100) function init(self) -- prints 100 to the output print(self.health) end function on_message(self, message_id, message, sender) if message_id == hash("take_damage") then self.health = self.health - message.damage print("Ouch! My health is now: " .. self.health) end end ``` ### go.set *Type:* FUNCTION sets a named property of the specified game object or component, or a material constant **Parameters** - `url` (string | hash | url) - url of the game object or component having the property - `property` (string | hash) - id of the property to set - `value` (number | boolean | hash | url | vector3 | vector4 | quaternion | resource) - the value to set - `options` (table) (optional) - optional options table - index integer index into array property (1 based) - key hash name of internal property - keys table array of internal component resources identified by key (e.g. a particle fx emitter, see examples below) **Examples** Set a property "speed" of a script "player", the property must be declared in the player-script: ``` go.property("speed", 50) ``` Then in the calling script (assumed to belong to the same game object, but does not have to): ``` go.set("#player", "speed", 100) ```Set a vector4 in a material property array ```lua -- set the first vector4 in the array: example[0] = v (the glsl indices are 0-based) go.set(url, "example", vmath.vector4(1,1,1,1), {index=1}) -- set the last vector4 in the array: example[15] = v (the glsl indices are 0-based) go.set(url, "example", vmath.vector4(2,2,2,2), {index=16}) -- set an element of a vector4 in the array: example[0].x = 7 (the glsl indices are 0-based) go.set(url, "example.x", 7, {index=1}) ``` Set a material property array by a table of vector4 lua -- set the first two vector4's in the array -- if the array has more than two elements in the array they will not be set go.set(url, "example", { vmath.vector4(1,1,1,1), vmath.vector4(2,2,2,2) })Set a named property ```lua go.property("big_font", resource.font()) function init(self) go.set("#gui", "fonts", self.big_font, {key = "system_font_BIG"}) end ```Set a property on a sub-component, using the "keys" options table lua go.property("my_material", resource.material) function init(self) go.set("#particlefx", "material", self.my_material, { keys = { "cone_emitter" } }) endSet a property in a deeper sub-hierarchy (if the component supports it). ```lua -- Note: There is currently no component that supports this, but a custom component could. go.set("#my_component", "some_property", some_value, { keys = { "root", "child_node" } }) ### go.set_parent *Type:* FUNCTION Sets the parent for a game object instance. This means that the instance will exist in the geometrical space of its parent, like a basic transformation hierarchy or scene graph. If no parent is specified, the instance will be detached from any parent and exist in world space. This function will generate a set_parent message. It is not until the message has been processed that the change actually takes effect. This typically happens later in the same frame or the beginning of the next frame. Refer to the manual to learn how messages are processed by the engine. **Parameters** - `id` (string | hash | url) (optional) - optional id of the game object instance to set parent for, defaults to the instance containing the calling script - `parent_id` (string | hash | url) (optional) - optional id of the new parent game object, defaults to detaching game object from its parent - `keep_world_transform` (boolean) (optional) - optional boolean, set to true to maintain the world transform when changing spaces. Defaults to false. **Examples** Attach myself to another instance "my_parent": ``` go.set_parent(go.get_id(),go.get_id("my_parent")) ``` Attach an instance "my_instance" to another instance "my_parent": ``` go.set_parent(go.get_id("my_instance"),go.get_id("my_parent")) ``` Detach an instance "my_instance" from its parent (if any): ``` go.set_parent(go.get_id("my_instance")) ``` ### go.set_position *Type:* FUNCTION The position is relative to the parent (if any). The global world position cannot be manually set. **Parameters** - `position` (vector3) - position to set - `id` (string | hash | url) (optional) - optional id of the game object instance to set the position for, by default the instance of the calling script **Examples** Set the position of the game object instance the script is attached to: ``` local p = ... go.set_position(p) ``` Set the position of another game object instance with id "x": ``` local p = ... go.set_position(p, "x") ``` ### go.set_rotation *Type:* FUNCTION The rotation is relative to the parent (if any). The global world rotation cannot be manually set. **Parameters** - `rotation` (quaternion) - rotation to set - `id` (string | hash | url) (optional) - optional id of the game object instance to get the rotation for, by default the instance of the calling script **Examples** Set the rotation of the game object instance the script is attached to: ``` local r = ... go.set_rotation(r) ``` Set the rotation of another game object instance with id "x": ``` local r = ... go.set_rotation(r, "x") ``` ### go.set_scale *Type:* FUNCTION The scale factor is relative to the parent (if any). The global world scale factor cannot be manually set. See manual to know how physics affected when setting scale from this function. **Parameters** - `scale` (number | vector3) - vector or uniform scale factor, must be greater than 0 - `id` (string | hash | url) (optional) - optional id of the game object instance to get the scale for, by default the instance of the calling script **Examples** Set the scale of the game object instance the script is attached to: ``` local s = vmath.vector3(2.0, 1.0, 1.0) go.set_scale(s) ``` Set the scale of another game object instance with id "obj_id": ``` local s = 1.2 go.set_scale(s, "obj_id") ``` ### go.set_scale_xy *Type:* FUNCTION The scale factor is relative to the parent (if any). The global world scale factor cannot be manually set. See manual to know how physics affected when setting scale from this function. **Parameters** - `scale` (number | vector3) - vector or uniform scale factor, must be greater than 0 - `id` (string | hash | url) (optional) - optional id of the game object instance to get the scale for, by default the instance of the calling script **Examples** Set the scale of the game object instance the script is attached to: ``` local s = vmath.vector3(2.0, 1.0, 5.0) go.set_scale_xy(s) -- z will not be set here, only x and y ``` Set the scale of another game object instance with id "obj_id": ``` local s = 1.2 go.set_scale_xy(s, "obj_id") -- z will not be set here, only x and y ``` ### go.update_world_transform *Type:* FUNCTION Recalculates and updates the cached world transform immediately for the target instance and its ancestors (parent chain up to the collection root). Descendants (children) are not updated by this function. If no id is provided, the instance of the calling script is used. Use this after changing local transform mid-frame when you need the new world transform right away (e.g. before end-of-frame updates). Note that child instances will still have last-frame world transforms until the regular update. **Parameters** - `id` (string | hash | url) (optional) - optional id of the game object instance to update **Examples** Update this game object's world transform: ``` go.update_world_transform() ``` Update another game object's world transform: ``` go.update_world_transform("/other") ``` ### go.world_to_local_position *Type:* FUNCTION The function uses world transformation calculated at the end of previous frame. **Parameters** - `position` (vector3) - position which need to be converted - `url` (string | hash | url) - url of the game object which coordinate system convert to **Returns** - `converted_postion` (vector3) - converted position **Examples** Convert position of "test" game object into coordinate space of "child" object. ``` local test_pos = go.get_world_position("/test") local child_pos = go.get_world_position("/child") local new_position = go.world_to_local_position(test_pos, "/child") ``` ### go.world_to_local_transform *Type:* FUNCTION The function uses world transformation calculated at the end of previous frame. **Parameters** - `transformation` (matrix4) - transformation which need to be converted - `url` (string | hash | url) - url of the game object which coordinate system convert to **Returns** - `converted_transform` (matrix4) - converted transformation **Examples** Convert transformation of "test" game object into coordinate space of "child" object. ``` local test_transform = go.get_world_transform("/test") local child_transform = go.get_world_transform("/child") local result_transform = go.world_to_local_transform(test_transform, "/child") ``` ### init *Type:* FUNCTION This is a callback-function, which is called by the engine when a script component is initialized. It can be used to set the initial state of the script. **Parameters** - `self` (userdata) - reference to the script state to be used for storing data **Examples** ``` function init(self) -- set up useful data self.my_value = 1 end ``` ### late_update *Type:* FUNCTION This is a callback-function, which is called by the engine at the end of the frame to update the state of a script component. Use it to make final adjustments to the game object instance. **Parameters** - `self` (userdata) - reference to the script state to be used for storing data - `dt` (number) - the time-step of the frame update ### on_input *Type:* FUNCTION This is a callback-function, which is called by the engine when user input is sent to the game object instance of the script. It can be used to take action on the input, e.g. move the instance according to the input. For an instance to obtain user input, it must first acquire input focus through the message acquire_input_focus. Any instance that has obtained input will be put on top of an input stack. Input is sent to all listeners on the stack until the end of stack is reached, or a listener returns true to signal that it wants input to be consumed. See the documentation of acquire_input_focus for more information. The action parameter is a table containing data about the input mapped to the action_id. For mapped actions it specifies the value of the input and if it was just pressed or released. Actions are mapped to input in an input_binding-file. Mouse movement is specifically handled and uses nil as its action_id. The action only contains positional parameters in this case, such as x and y of the pointer. Here is a brief description of the available table fields: Field Description value The amount of input given by the user. This is usually 1 for buttons and 0-1 for analogue inputs. This is not present for mouse movement and text input. pressed If the input was pressed this frame. This is not present for mouse movement and text input. released If the input was released this frame. This is not present for mouse movement and text input. repeated If the input was repeated this frame. This is similar to how a key on a keyboard is repeated when you hold it down. This is not present for mouse movement and text input. x The x value of a pointer device, if present. This is not present for gamepad, key and text input. y The y value of a pointer device, if present. This is not present for gamepad, key and text input. screen_x The screen space x value of a pointer device, if present. This is not present for gamepad, key and text input. screen_y The screen space y value of a pointer device, if present. This is not present for gamepad, key and text input. dx The change in x value of a pointer device, if present. This is not present for gamepad, key and text input. dy The change in y value of a pointer device, if present. This is not present for gamepad, key and text input. screen_dx The change in screen space x value of a pointer device, if present. This is not present for gamepad, key and text input. screen_dy The change in screen space y value of a pointer device, if present. This is not present for gamepad, key and text input. gamepad The index of the gamepad device that provided the input. See table below about gamepad input. touch List of touch input, one element per finger, if present. See table below about touch input text Text input from a (virtual) keyboard or similar. marked_text Sequence of entered symbols while entering a symbol combination, for example Japanese Kana. Gamepad specific fields: Field Description gamepad The index of the gamepad device that provided the input. userid Id of the user associated with the controller. Usually only relevant on consoles. gamepad_unknown True if the inout originated from an unknown/unmapped gamepad. gamepad_name Name of the gamepad gamepad_axis List of gamepad axis values. For raw gamepad input only. gamepadhats List of gamepad hat values. For raw gamepad input only. gamepad_buttons List of gamepad button values. For raw gamepad input only. Touch input table: Field Description id A number identifying the touch input during its duration. pressed True if the finger was pressed this frame. released True if the finger was released this frame. tap_count Number of taps, one for single, two for double-tap, etc x The x touch location. y The y touch location. dx The change in x value. dy The change in y value. acc_x Accelerometer x value (if present). acc_y Accelerometer y value (if present). acc_z Accelerometer z value (if present). **Parameters** - `self` (userdata) - reference to the script state to be used for storing data - `action_id` (hash) - id of the received input action, as mapped in the input_binding-file - `action` (table) - a table containing the input data, see above for a description **Returns** - `consume` (boolean | nil) - optional boolean to signal if the input should be consumed (not passed on to others) or not, default is false **Examples** This example demonstrates how a game object instance can be moved as a response to user input. ``` function init(self) -- acquire input focus msg.post(".", "acquire_input_focus") -- maximum speed the instance can be moved self.max_speed = 2 -- velocity of the instance, initially zero self.velocity = vmath.vector3() end function update(self, dt) -- move the instance go.set_position(go.get_position() + dt * self.velocity) end function on_input(self, action_id, action) -- check for movement input if action_id == hash("right") then if action.released then -- reset velocity if input was released self.velocity = vmath.vector3() else -- update velocity self.velocity = vmath.vector3(action.value * self.max_speed, 0, 0) end end end ``` ### on_message *Type:* FUNCTION This is a callback-function, which is called by the engine whenever a message has been sent to the script component. It can be used to take action on the message, e.g. send a response back to the sender of the message. The message parameter is a table containing the message data. If the message is sent from the engine, the documentation of the message specifies which data is supplied. **Parameters** - `self` (userdata) - reference to the script state to be used for storing data - `message_id` (hash) - id of the received message - `message` (table) - a table containing the message data - `sender` (url) - address of the sender **Examples** This example demonstrates how a game object instance, called "a", can communicate with another instance, called "b". It is assumed that both script components of the instances has id "script". Script of instance "a": ``` function init(self) -- let b know about some important data msg.post("b#script", "my_data", {important_value = 1}) end ``` Script of instance "b": ``` function init(self) -- store the url of instance "a" for later use, by specifying nil as socket we -- automatically use our own socket self.a_url = msg.url(nil, go.get_id("a"), "script") end function on_message(self, message_id, message, sender) -- check message and sender if message_id == hash("my_data") and sender == self.a_url then -- use the data in some way self.important_value = message.important_value end end ``` ### on_reload *Type:* FUNCTION This is a callback-function, which is called by the engine when the script component is reloaded, e.g. from the editor. It can be used for live development, e.g. to tweak constants or set up the state properly for the instance. **Parameters** - `self` (userdata) - reference to the script state to be used for storing data **Examples** This example demonstrates how to tweak the speed of a game object instance that is moved on user input. ``` function init(self) -- acquire input focus msg.post(".", "acquire_input_focus") -- maximum speed the instance can be moved, this value is tweaked in the on_reload function below self.max_speed = 2 -- velocity of the instance, initially zero self.velocity = vmath.vector3() end function update(self, dt) -- move the instance go.set_position(go.get_position() + dt * self.velocity) end function on_input(self, action_id, action) -- check for movement input if action_id == hash("right") then if action.released then -- reset velocity if input was released self.velocity = vmath.vector3() else -- update velocity self.velocity = vmath.vector3(action.value * self.max_speed, 0, 0) end end end function on_reload(self) -- edit this value and reload the script component self.max_speed = 100 end ``` ### position *Type:* PROPERTY The position of the game object. The type of the property is vector3. **Examples** How to query a game object's position, either as a vector3 or selecting a specific dimension: ``` function init(self) -- get position from "player" local pos = go.get("player", "position") local posx = go.get("player", "position.x") -- do something useful assert(pos.x == posx) end ``` ### release_input_focus *Type:* MESSAGE Post this message to an instance to make that instance release the user input focus. See acquire_input_focus for more information on how the user input handling works. **Examples** How to make a game object stop receiving input: ``` msg.post(".", "release_input_focus") ``` ### rotation *Type:* PROPERTY The rotation of the game object. The type of the property is quaternion. **Examples** How to set a game object's rotation: ``` function init(self) -- set "player" rotation to 45 degrees around z. local rotz = vmath.quat_rotation_z(3.141592 / 4) go.set("player", "rotation", rotz) end ``` ### scale *Type:* PROPERTY The uniform scale of the game object. The type of the property is number. **Examples** How to scale a game object: ``` function init(self) -- Double the scaling on "player" local scale = go.get("player", "scale") go.set("player", "scale", scale * 2) end ``` ### set_parent *Type:* MESSAGE When this message is sent to an instance, it sets the parent of that instance. This means that the instance will exist in the geometrical space of its parent, like a basic transformation hierarchy or scene graph. If no parent is specified, the instance will be detached from any parent and exist in world space. A script can send this message to itself to set the parent of its instance. **Parameters** - `parent_id` (hash) - the id of the new parent - `keep_world_transform` (number) - if the world transform of the instance should be preserved when changing spaces, 0 for false and 1 for true. The default value is 1. **Examples** Attach myself to another instance "my_parent": ``` msg.post(".", "set_parent", {parent_id = go.get_id("my_parent")}) ``` Attach an instance "my_instance" to another instance "my_parent": ``` msg.post("my_instance", "set_parent", {parent_id = go.get_id("my_parent")}) ``` Detach an instance "my_instance" from its parent (if any): ``` msg.post("my_instance", "set_parent") ``` ### update *Type:* FUNCTION This is a callback-function, which is called by the engine every frame to update the state of a script component. It can be used to perform any kind of game related tasks, e.g. moving the game object instance. **Parameters** - `self` (userdata) - reference to the script state to be used for storing data - `dt` (number) - the time-step of the frame update **Examples** This example demonstrates how to move a game object instance through the script component: ``` function init(self) -- set initial velocity to be 1 along world x-axis self.my_velocity = vmath.vector3(1, 0, 0) end function update(self, dt) -- move the game object instance go.set_position(go.get_position() + dt * self.my_velocity) end ``` # Graphics {#apis:graphics-lua} **Namespace:** `graphics` **Language:** Lua **Type:** Defold Lua **File:** `script_graphics.cpp` **Source:** `engine/script/src/script_graphics.cpp` Graphics functions and constants. ## API ### graphics.BLEND_FACTOR_CONSTANT_ALPHA *Type:* CONSTANT ### graphics.BLEND_FACTOR_CONSTANT_COLOR *Type:* CONSTANT ### graphics.BLEND_FACTOR_DST_ALPHA *Type:* CONSTANT ### graphics.BLEND_FACTOR_DST_COLOR *Type:* CONSTANT ### graphics.BLEND_FACTOR_ONE *Type:* CONSTANT ### graphics.BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA *Type:* CONSTANT ### graphics.BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR *Type:* CONSTANT ### graphics.BLEND_FACTOR_ONE_MINUS_DST_ALPHA *Type:* CONSTANT ### graphics.BLEND_FACTOR_ONE_MINUS_DST_COLOR *Type:* CONSTANT ### graphics.BLEND_FACTOR_ONE_MINUS_SRC_ALPHA *Type:* CONSTANT ### graphics.BLEND_FACTOR_ONE_MINUS_SRC_COLOR *Type:* CONSTANT ### graphics.BLEND_FACTOR_SRC_ALPHA *Type:* CONSTANT ### graphics.BLEND_FACTOR_SRC_ALPHA_SATURATE *Type:* CONSTANT ### graphics.BLEND_FACTOR_SRC_COLOR *Type:* CONSTANT ### graphics.BLEND_FACTOR_ZERO *Type:* CONSTANT ### graphics.BUFFER_TYPE_COLOR0_BIT *Type:* CONSTANT ### graphics.BUFFER_TYPE_COLOR1_BIT *Type:* CONSTANT May be nil if multitarget rendering isn't supported ### graphics.BUFFER_TYPE_COLOR2_BIT *Type:* CONSTANT May be nil if multitarget rendering isn't supported ### graphics.BUFFER_TYPE_COLOR3_BIT *Type:* CONSTANT May be nil if multitarget rendering isn't supported ### graphics.BUFFER_TYPE_DEPTH_BIT *Type:* CONSTANT ### graphics.BUFFER_TYPE_STENCIL_BIT *Type:* CONSTANT ### graphics.COMPARE_FUNC_ALWAYS *Type:* CONSTANT ### graphics.COMPARE_FUNC_EQUAL *Type:* CONSTANT ### graphics.COMPARE_FUNC_GEQUAL *Type:* CONSTANT ### graphics.COMPARE_FUNC_GREATER *Type:* CONSTANT ### graphics.COMPARE_FUNC_LEQUAL *Type:* CONSTANT ### graphics.COMPARE_FUNC_LESS *Type:* CONSTANT ### graphics.COMPARE_FUNC_NEVER *Type:* CONSTANT ### graphics.COMPARE_FUNC_NOTEQUAL *Type:* CONSTANT ### graphics.COMPRESSION_TYPE_BASIS_ETC1S *Type:* CONSTANT ### graphics.COMPRESSION_TYPE_BASIS_UASTC *Type:* CONSTANT ### graphics.COMPRESSION_TYPE_DEFAULT *Type:* CONSTANT ### graphics.COMPRESSION_TYPE_WEBP *Type:* CONSTANT ### graphics.COMPRESSION_TYPE_WEBP_LOSSY *Type:* CONSTANT ### graphics.FACE_TYPE_BACK *Type:* CONSTANT ### graphics.FACE_TYPE_FRONT *Type:* CONSTANT ### graphics.FACE_TYPE_FRONT_AND_BACK *Type:* CONSTANT ### graphics.STATE_ALPHA_TEST *Type:* CONSTANT ### graphics.STATE_ALPHA_TEST_SUPPORTED *Type:* CONSTANT ### graphics.STATE_BLEND *Type:* CONSTANT ### graphics.STATE_CULL_FACE *Type:* CONSTANT ### graphics.STATE_DEPTH_TEST *Type:* CONSTANT ### graphics.STATE_POLYGON_OFFSET_FILL *Type:* CONSTANT ### graphics.STATE_SCISSOR_TEST *Type:* CONSTANT ### graphics.STATE_STENCIL_TEST *Type:* CONSTANT ### graphics.STENCIL_OP_DECR *Type:* CONSTANT ### graphics.STENCIL_OP_DECR_WRAP *Type:* CONSTANT ### graphics.STENCIL_OP_INCR *Type:* CONSTANT ### graphics.STENCIL_OP_INCR_WRAP *Type:* CONSTANT ### graphics.STENCIL_OP_INVERT *Type:* CONSTANT ### graphics.STENCIL_OP_KEEP *Type:* CONSTANT ### graphics.STENCIL_OP_REPLACE *Type:* CONSTANT ### graphics.STENCIL_OP_ZERO *Type:* CONSTANT ### graphics.TEXTURE_FILTER_DEFAULT *Type:* CONSTANT ### graphics.TEXTURE_FILTER_LINEAR *Type:* CONSTANT ### graphics.TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR *Type:* CONSTANT ### graphics.TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST *Type:* CONSTANT ### graphics.TEXTURE_FILTER_NEAREST *Type:* CONSTANT ### graphics.TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR *Type:* CONSTANT ### graphics.TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST *Type:* CONSTANT ### graphics.TEXTURE_FORMAT_BGRA8U *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_DEPTH *Type:* CONSTANT ### graphics.TEXTURE_FORMAT_LUMINANCE *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_LUMINANCE_ALPHA *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_R16F *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_R32F *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_R32UI *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_R_BC4 *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_R_ETC2 *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RG16F *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RG32F *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RG_BC5 *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RG_ETC2 *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGB *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGB16F *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGB32F *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGB_16BPP *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGB_BC1 *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGB_ETC1 *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGB_PVRTC_2BPPV1 *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGB_PVRTC_4BPPV1 *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGBA *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGBA16F *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGBA32F *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGBA32UI *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGBA_16BPP *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGBA_ASTC_4X4 *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGBA_BC3 *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGBA_BC7 *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGBA_ETC2 *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGBA_PVRTC_2BPPV1 *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_RGBA_PVRTC_4BPPV1 *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_FORMAT_STENCIL *Type:* CONSTANT ### graphics.TEXTURE_TYPE_2D *Type:* CONSTANT ### graphics.TEXTURE_TYPE_2D_ARRAY *Type:* CONSTANT ### graphics.TEXTURE_TYPE_3D *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_TYPE_CUBE_MAP *Type:* CONSTANT ### graphics.TEXTURE_TYPE_IMAGE_2D *Type:* CONSTANT ### graphics.TEXTURE_TYPE_IMAGE_3D *Type:* CONSTANT May be nil if the graphics driver doesn't support it ### graphics.TEXTURE_USAGE_FLAG_COLOR *Type:* CONSTANT ### graphics.TEXTURE_USAGE_FLAG_INPUT *Type:* CONSTANT ### graphics.TEXTURE_USAGE_FLAG_MEMORYLESS *Type:* CONSTANT ### graphics.TEXTURE_USAGE_FLAG_SAMPLE *Type:* CONSTANT ### graphics.TEXTURE_USAGE_FLAG_STORAGE *Type:* CONSTANT ### graphics.TEXTURE_WRAP_CLAMP_TO_BORDER *Type:* CONSTANT ### graphics.TEXTURE_WRAP_CLAMP_TO_EDGE *Type:* CONSTANT ### graphics.TEXTURE_WRAP_MIRRORED_REPEAT *Type:* CONSTANT ### graphics.TEXTURE_WRAP_REPEAT *Type:* CONSTANT # GUI {#apis:gui-lua} **Namespace:** `gui` **Language:** Lua **Type:** Defold Lua **File:** `gui_ddf.proto` **Source:** `engine/gamesys/proto/gamesys/gui_ddf.proto` GUI API documentation ## API ### final *Type:* FUNCTION This is a callback-function, which is called by the engine when a gui component is finalized (destroyed). It can be used to e.g. take some last action, report the finalization to other game object instances or release user input focus (see release_input_focus). There is no use in starting any animations or similar from this function since the gui component is about to be destroyed. **Parameters** - `self` (userdata) - reference to the script state to be used for storing data **Examples** ``` function final(self) -- report finalization msg.post("my_friend_instance", "im_dead", {my_stats = self.some_value}) end ``` ### fonts *Type:* PROPERTY The fonts used in the gui. The type of the property is hash. Key must be specified in options table. **Examples** How to set font using a script property (see resource.font) ``` go.property("title_latin", resource.font("/open_sans.font")) go.property("title_cyrillic", resource.font("/open_sans_cyrillic.font")) function init(self) go.set("#gui", "fonts", self.title_cyrillic, {key = "title"}) end ``` ### gui.ADJUST_FIT *Type:* CONSTANT Adjust mode is used when the screen resolution differs from the project settings. The fit mode ensures that the entire node is visible in the adjusted gui scene. ### gui.ADJUST_STRETCH *Type:* CONSTANT Adjust mode is used when the screen resolution differs from the project settings. The stretch mode ensures that the node is displayed as is in the adjusted gui scene, which might scale it non-uniformally. ### gui.ADJUST_ZOOM *Type:* CONSTANT Adjust mode is used when the screen resolution differs from the project settings. The zoom mode ensures that the node fills its entire area and might make the node exceed it. ### gui.ANCHOR_BOTTOM *Type:* CONSTANT bottom y-anchor ### gui.ANCHOR_LEFT *Type:* CONSTANT left x-anchor ### gui.ANCHOR_NONE *Type:* CONSTANT no anchor ### gui.ANCHOR_RIGHT *Type:* CONSTANT right x-anchor ### gui.ANCHOR_TOP *Type:* CONSTANT top y-anchor ### gui.animate *Type:* FUNCTION This starts an animation of a node property according to the specified parameters. If the node property is already being animated, that animation will be canceled and replaced by the new one. Note however that several different node properties can be animated simultaneously. Use gui.cancel_animations to stop the animation before it has completed. Composite properties of type vector3, vector4 or quaternion also expose their sub-components (x, y, z and w). You can address the components individually by suffixing the name with a dot '.' and the name of the component. For instance, "position.x" (the position x coordinate) or "color.w" (the color alpha value). If a complete_function (Lua function) is specified, that function will be called when the animation has completed. By starting a new animation in that function, several animations can be sequenced together. See the examples below for more information. **Parameters** - `node` (node) - node to animate - `property` (string | constant) - property to animate
  • "position"
  • "rotation"
  • "euler"
  • "scale"
  • "color"
  • "outline"
  • "shadow"
  • "size"
  • "fill_angle" (pie)
  • "inner_radius" (pie)
  • "leading" (text)
  • "tracking" (text)
  • "slice9" (slice9)
The following property constants are defined equaling the corresponding property string names.
  • gui.PROP_POSITION
  • gui.PROP_ROTATION
  • gui.PROP_EULER
  • gui.PROP_SCALE
  • gui.PROP_COLOR
  • gui.PROP_OUTLINE
  • gui.PROP_SHADOW
  • gui.PROP_SIZE
  • gui.PROP_FILL_ANGLE
  • gui.PROP_INNER_RADIUS
  • gui.PROP_LEADING
  • gui.PROP_TRACKING
  • gui.PROP_SLICE9
- `to` (number | vector3 | vector4 | quaternion) - target property value - `easing` (constant | vector) - easing to use during animation. Either specify one of the gui.EASING_* constants or provide a vector with a custom curve. See the animation guide for more information. - `duration` (number) - duration of the animation in seconds. - `delay` (number) (optional) - delay before the animation starts in seconds. - `complete_function` (function(self, node)) (optional) - function to call when the animation has completed - `playback` (constant) (optional) - playback mode
  • gui.PLAYBACK_ONCE_FORWARD
  • gui.PLAYBACK_ONCE_BACKWARD
  • gui.PLAYBACK_ONCE_PINGPONG
  • gui.PLAYBACK_LOOP_FORWARD
  • gui.PLAYBACK_LOOP_BACKWARD
  • gui.PLAYBACK_LOOP_PINGPONG
**Examples** How to start a simple color animation, where the node fades in to white during 0.5 seconds: ``` gui.set_color(node, vmath.vector4(0, 0, 0, 0)) -- node is fully transparent gui.animate(node, gui.PROP_COLOR, vmath.vector4(1, 1, 1, 1), gui.EASING_INOUTQUAD, 0.5) -- start animation ``` How to start a sequenced animation where the node fades in to white during 0.5 seconds, stays visible for 2 seconds and then fades out: ``` local function on_animation_done(self, node) -- fade out node, but wait 2 seconds before the animation starts gui.animate(node, gui.PROP_COLOR, vmath.vector4(0, 0, 0, 0), gui.EASING_OUTQUAD, 0.5, 2.0) end function init(self) -- fetch the node we want to animate local my_node = gui.get_node("my_node") -- node is initially set to fully transparent gui.set_color(my_node, vmath.vector4(0, 0, 0, 0)) -- animate the node immediately and call on_animation_done when the animation has completed gui.animate(my_node, gui.PROP_COLOR, vmath.vector4(1, 1, 1, 1), gui.EASING_INOUTQUAD, 0.5, 0.0, on_animation_done) end ``` How to animate a node's y position using a crazy custom easing curve: ``` function init(self) local values = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 } local vec = vmath.vector(values) local node = gui.get_node("box") gui.animate(node, "position.y", 100, vec, 4.0, 0, nil, gui.PLAYBACK_LOOP_PINGPONG) end ``` ### gui.BLEND_ADD *Type:* CONSTANT additive blending ### gui.BLEND_ADD_ALPHA *Type:* CONSTANT additive alpha blending ### gui.BLEND_ALPHA *Type:* CONSTANT alpha blending ### gui.BLEND_MULT *Type:* CONSTANT multiply blending ### gui.BLEND_SCREEN *Type:* CONSTANT screen blending ### gui.cancel_animations *Type:* FUNCTION If one or more animations of the specified node is currently running (started by gui.animate), they will immediately be canceled. **Parameters** - `node` (node) - node that should have its animation canceled - `property` (nil | string | constant) (optional) - optional property for which the animation should be canceled
  • "position"
  • "rotation"
  • "euler"
  • "scale"
  • "color"
  • "outline"
  • "shadow"
  • "size"
  • "fill_angle" (pie)
  • "inner_radius" (pie)
  • "leading" (text)
  • "tracking" (text)
  • "slice9" (slice9)
**Examples** Start an animation of the position property of a node, then cancel parts of the animation: ``` local node = gui.get_node("my_node") -- animate to new position local pos = vmath.vector3(100, 100, 0) gui.animate(node, "position", pos, go.EASING_LINEAR, 2) ... -- cancel animation of the x component. gui.cancel_animations(node, "position.x") ``` Cancels all property animations on a node in a single call: ``` local node = gui.get_node("my_node") -- animate to new position and scale gui.animate(node, "position", vmath.vector3(100, 100, 0), go.EASING_LINEAR, 5) gui.animate(node, "scale", vmath.vector3(0.5), go.EASING_LINEAR, 5) ... -- cancel positioning and scaling at once gui.cancel_animations(node) ``` ### gui.cancel_flipbook *Type:* FUNCTION Cancels any running flipbook animation on the specified node. **Parameters** - `node` (node) - node cancel flipbook animation for **Examples** ``` local node = gui.get_node("anim_node") gui.cancel_flipbook(node) ``` ### gui.CLIPPING_MODE_NONE *Type:* CONSTANT clipping mode none ### gui.CLIPPING_MODE_STENCIL *Type:* CONSTANT clipping mode stencil ### gui.clone *Type:* FUNCTION Make a clone instance of a node. The cloned node will be identical to the original node, except the id which is generated as the string "node" plus a sequential unsigned integer value. This function does not clone the supplied node's children nodes. Use gui.clone_tree for that purpose. **Parameters** - `node` (node) - node to clone **Returns** - `clone` (node) - the cloned node ### gui.clone_tree *Type:* FUNCTION Make a clone instance of a node and all its children. Use gui.clone to clone a node excluding its children. **Parameters** - `node` (node) - root node to clone **Returns** - `clones` (table) - a table mapping node ids to the corresponding cloned nodes ### gui.delete_node *Type:* FUNCTION Deletes the specified node. Any child nodes of the specified node will be recursively deleted. **Parameters** - `node` (node) - node to delete **Examples** Delete a particular node and any child nodes it might have: ``` local node = gui.get_node("my_node") gui.delete_node(node) ``` ### gui.delete_texture *Type:* FUNCTION Delete a dynamically created texture. **Parameters** - `texture` (string | hash) - texture id **Examples** ``` function init(self) -- Create a texture. if gui.new_texture("temp_tx", 10, 10, "rgb", string.rep('\0', 10 * 10 * 3)) then -- Do something with the texture. ... -- Delete the texture gui.delete_texture("temp_tx") end end ``` ### gui.EASING_INBACK *Type:* CONSTANT in-back ### gui.EASING_INBOUNCE *Type:* CONSTANT in-bounce ### gui.EASING_INCIRC *Type:* CONSTANT in-circlic ### gui.EASING_INCUBIC *Type:* CONSTANT in-cubic ### gui.EASING_INELASTIC *Type:* CONSTANT in-elastic ### gui.EASING_INEXPO *Type:* CONSTANT in-exponential ### gui.EASING_INOUTBACK *Type:* CONSTANT in-out-back ### gui.EASING_INOUTBOUNCE *Type:* CONSTANT in-out-bounce ### gui.EASING_INOUTCIRC *Type:* CONSTANT in-out-circlic ### gui.EASING_INOUTCUBIC *Type:* CONSTANT in-out-cubic ### gui.EASING_INOUTELASTIC *Type:* CONSTANT in-out-elastic ### gui.EASING_INOUTEXPO *Type:* CONSTANT in-out-exponential ### gui.EASING_INOUTQUAD *Type:* CONSTANT in-out-quadratic ### gui.EASING_INOUTQUART *Type:* CONSTANT in-out-quartic ### gui.EASING_INOUTQUINT *Type:* CONSTANT in-out-quintic ### gui.EASING_INOUTSINE *Type:* CONSTANT in-out-sine ### gui.EASING_INQUAD *Type:* CONSTANT in-quadratic ### gui.EASING_INQUART *Type:* CONSTANT in-quartic ### gui.EASING_INQUINT *Type:* CONSTANT in-quintic ### gui.EASING_INSINE *Type:* CONSTANT in-sine ### gui.EASING_LINEAR *Type:* CONSTANT linear interpolation ### gui.EASING_OUTBACK *Type:* CONSTANT out-back ### gui.EASING_OUTBOUNCE *Type:* CONSTANT out-bounce ### gui.EASING_OUTCIRC *Type:* CONSTANT out-circlic ### gui.EASING_OUTCUBIC *Type:* CONSTANT out-cubic ### gui.EASING_OUTELASTIC *Type:* CONSTANT out-elastic ### gui.EASING_OUTEXPO *Type:* CONSTANT out-exponential ### gui.EASING_OUTINBACK *Type:* CONSTANT out-in-back ### gui.EASING_OUTINBOUNCE *Type:* CONSTANT out-in-bounce ### gui.EASING_OUTINCIRC *Type:* CONSTANT out-in-circlic ### gui.EASING_OUTINCUBIC *Type:* CONSTANT out-in-cubic ### gui.EASING_OUTINELASTIC *Type:* CONSTANT out-in-elastic ### gui.EASING_OUTINEXPO *Type:* CONSTANT out-in-exponential ### gui.EASING_OUTINQUAD *Type:* CONSTANT out-in-quadratic ### gui.EASING_OUTINQUART *Type:* CONSTANT out-in-quartic ### gui.EASING_OUTINQUINT *Type:* CONSTANT out-in-quintic ### gui.EASING_OUTINSINE *Type:* CONSTANT out-in-sine ### gui.EASING_OUTQUAD *Type:* CONSTANT out-quadratic ### gui.EASING_OUTQUART *Type:* CONSTANT out-quartic ### gui.EASING_OUTQUINT *Type:* CONSTANT out-quintic ### gui.EASING_OUTSINE *Type:* CONSTANT out-sine ### gui.get *Type:* FUNCTION Instead of using specific getters such as gui.get_position or gui.get_scale, you can use gui.get instead and supply the property as a string or a hash. While this function is similar to go.get, there are a few more restrictions when operating in the gui namespace. Most notably, only these explicitly named properties are supported: "position" "rotation" "euler" "scale" "color" "outline" "shadow" "size" "fill_angle" (pie) "inner_radius" (pie) "leading" (text) "tracking" (text) "slice9" (slice9) The value returned will either be a vmath.vector4 or a single number, i.e getting the "position" property will return a vec4 while getting the "position.x" property will return a single value. You can also use this function to get material constants. **Parameters** - `node` (node) - node to get the property for - `property` (string | hash | constant) - the property to retrieve - `options` (table) (optional) - optional options table (only applicable for material constants) - index number index into array property (1 based) **Examples** Get properties on existing nodes: ``` local node = gui.get_node("my_box_node") local node_position = gui.get(node, "position") ``` ### gui.get_adjust_mode *Type:* FUNCTION Returns the adjust mode of a node. The adjust mode defines how the node will adjust itself to screen resolutions that differs from the one in the project settings. **Parameters** - `node` (node) - node from which to get the adjust mode (node) **Returns** - `adjust_mode` (constant) - the current adjust mode
  • gui.ADJUST_FIT
  • gui.ADJUST_ZOOM
  • gui.ADJUST_STRETCH
### gui.get_alpha *Type:* FUNCTION gets the node alpha **Parameters** - `node` (node) - node from which to get alpha **Returns** - `alpha` (number) - alpha ### gui.get_blend_mode *Type:* FUNCTION Returns the blend mode of a node. Blend mode defines how the node will be blended with the background. **Parameters** - `node` (node) - node from which to get the blend mode **Returns** - `blend_mode` (constant) - blend mode
  • gui.BLEND_ALPHA
  • gui.BLEND_ADD
  • gui.BLEND_ADD_ALPHA
  • gui.BLEND_MULT
  • gui.BLEND_SCREEN
### gui.get_clipping_inverted *Type:* FUNCTION If node is set as an inverted clipping node, it will clip anything inside as opposed to outside. **Parameters** - `node` (node) - node from which to get the clipping inverted state **Returns** - `inverted` (boolean) - true or false ### gui.get_clipping_mode *Type:* FUNCTION Clipping mode defines how the node will clip it's children nodes **Parameters** - `node` (node) - node from which to get the clipping mode **Returns** - `clipping_mode` (constant) - clipping mode
  • gui.CLIPPING_MODE_NONE
  • gui.CLIPPING_MODE_STENCIL
### gui.get_clipping_visible *Type:* FUNCTION If node is set as visible clipping node, it will be shown as well as clipping. Otherwise, it will only clip but not show visually. **Parameters** - `node` (node) - node from which to get the clipping visibility state **Returns** - `visible` (boolean) - true or false ### gui.get_color *Type:* FUNCTION Returns the color of the supplied node. The components of the returned vector4 contains the color channel values: Component Color value x Red value y Green value z Blue value w Alpha value **Parameters** - `node` (node) - node to get the color from **Returns** - `color` (vector4) - node color ### gui.get_euler *Type:* FUNCTION Returns the rotation of the supplied node. The rotation is expressed in degree Euler angles. **Parameters** - `node` (node) - node to get the rotation from **Returns** - `rotation` (vector3) - node rotation ### gui.get_fill_angle *Type:* FUNCTION Returns the sector angle of a pie node. **Parameters** - `node` (node) - node from which to get the fill angle **Returns** - `angle` (number) - sector angle ### gui.get_flipbook *Type:* FUNCTION Get node flipbook animation. **Parameters** - `node` (node) - node to get flipbook animation from **Returns** - `animation` (hash) - animation id ### gui.get_flipbook_cursor *Type:* FUNCTION This is only useful nodes with flipbook animations. Gets the normalized cursor of the flipbook animation on a node. **Parameters** - `node` (node) - node to get the cursor for (node) **Returns** - `cursor` (number) - cursor value ### gui.get_flipbook_playback_rate *Type:* FUNCTION This is only useful nodes with flipbook animations. Gets the playback rate of the flipbook animation on a node. **Parameters** - `node` (node) - node to set the cursor for **Returns** - `rate` (number) - playback rate ### gui.get_font *Type:* FUNCTION This is only useful for text nodes. The font must be mapped to the gui scene in the gui editor. **Parameters** - `node` (node) - node from which to get the font **Returns** - `font` (hash) - font id ### gui.get_font_resource *Type:* FUNCTION This is only useful for text nodes. The font must be mapped to the gui scene in the gui editor. **Parameters** - `font_name` (hash | string) - font of which to get the path hash **Returns** - `hash` (hash) - path hash to resource **Examples** Get the text metrics for a text ``` function init(self) local node = gui.get_node("name") local font_name = gui.get_font(node) local font = gui.get_font_resource(font_name) local metrics = resource.get_text_metrics(font, "The quick brown fox\n jumps over the lazy dog") end ``` ### gui.get_height *Type:* FUNCTION Returns the scene height. **Returns** - `height` (number) - scene height ### gui.get_id *Type:* FUNCTION Retrieves the id of the specified node. **Parameters** - `node` (node) - the node to retrieve the id from **Returns** - `id` (hash) - the id of the node **Examples** Gets the id of a node: ``` local node = gui.get_node("my_node") local id = gui.get_id(node) print(id) --> hash: [my_node] ``` ### gui.get_index *Type:* FUNCTION Retrieve the index of the specified node among its siblings. The index defines the order in which a node appear in a GUI scene. Higher index means the node is drawn on top of lower indexed nodes. **Parameters** - `node` (node) - the node to retrieve the id from **Returns** - `index` (number) - the index of the node **Examples** Compare the index order of two sibling nodes: ``` local node1 = gui.get_node("my_node_1") local node2 = gui.get_node("my_node_2") if gui.get_index(node1) < gui.get_index(node2) then -- node1 is drawn below node2 else -- node2 is drawn below node1 end ``` ### gui.get_inherit_alpha *Type:* FUNCTION gets the node inherit alpha state **Parameters** - `node` (node) - node from which to get the inherit alpha state **Returns** - `inherit_alpha` (boolean) - true or false ### gui.get_inner_radius *Type:* FUNCTION Returns the inner radius of a pie node. The radius is defined along the x-axis. **Parameters** - `node` (node) - node from where to get the inner radius **Returns** - `radius` (number) - inner radius ### gui.get_layer *Type:* FUNCTION The layer must be mapped to the gui scene in the gui editor. **Parameters** - `node` (node) - node from which to get the layer **Returns** - `layer` (hash) - layer id ### gui.get_layout *Type:* FUNCTION gets the scene current layout **Returns** - `layout` (hash) - layout id ### gui.get_layouts *Type:* FUNCTION Returns a table mapping each layout id hash to a vector3(width, height, 0). For the default layout, the current scene resolution is returned. If a layout name is not present in the Display Profiles (or when no display profiles are assigned), the width/height pair is 0. **Returns** - `return` (table) - layout_id_hash -> vmath.vector3(width, height, 0) ### gui.get_leading *Type:* FUNCTION Returns the leading value for a text node. **Parameters** - `node` (node) - node from where to get the leading **Returns** - `leading` (number) - leading scaling value (default=1) ### gui.get_line_break *Type:* FUNCTION Returns whether a text node is in line-break mode or not. This is only useful for text nodes. **Parameters** - `node` (node) - node from which to get the line-break for **Returns** - `line_break` (boolean) - true or false ### gui.get_material *Type:* FUNCTION Returns the material of a node. The material must be mapped to the gui scene in the gui editor. **Parameters** - `node` (node) - node to get the material for **Returns** - `materal` (hash) - material id **Examples** Getting the material for a node, and assign it to another node: ``` local node1 = gui.get_node("my_node") local node2 = gui.get_node("other_node") local node1_material = gui.get_material(node1) gui.set_material(node2, node1_material) ``` ### gui.get_node *Type:* FUNCTION Retrieves the node with the specified id. **Parameters** - `id` (string | hash) - id of the node to retrieve **Returns** - `instance` (node) - a new node instance **Examples** Gets a node by id and change its color: ``` local node = gui.get_node("my_node") local red = vmath.vector4(1.0, 0.0, 0.0, 1.0) gui.set_color(node, red) ``` ### gui.get_outer_bounds *Type:* FUNCTION Returns the outer bounds mode for a pie node. **Parameters** - `node` (node) - node from where to get the outer bounds mode **Returns** - `bounds_mode` (constant) - the outer bounds mode of the pie node:
  • gui.PIEBOUNDS_RECTANGLE
  • gui.PIEBOUNDS_ELLIPSE
### gui.get_outline *Type:* FUNCTION Returns the outline color of the supplied node. See gui.get_color for info how vectors encode color values. **Parameters** - `node` (node) - node to get the outline color from **Returns** - `color` (vector4) - outline color ### gui.get_parent *Type:* FUNCTION Returns the parent node of the specified node. If the supplied node does not have a parent, nil is returned. **Parameters** - `node` (node) - the node from which to retrieve its parent **Returns** - `parent` (node | nil) - parent instance or nil ### gui.get_particlefx *Type:* FUNCTION Get the paricle fx for a gui node **Parameters** - `node` (node) - node to get particle fx for **Returns** - `particlefx` (hash) - particle fx id ### gui.get_perimeter_vertices *Type:* FUNCTION Returns the number of generated vertices around the perimeter of a pie node. **Parameters** - `node` (node) - pie node **Returns** - `vertices` (number) - vertex count ### gui.get_pivot *Type:* FUNCTION The pivot specifies how the node is drawn and rotated from its position. **Parameters** - `node` (node) - node to get pivot from **Returns** - `pivot` (constant) - pivot constant
  • gui.PIVOT_CENTER
  • gui.PIVOT_N
  • gui.PIVOT_NE
  • gui.PIVOT_E
  • gui.PIVOT_SE
  • gui.PIVOT_S
  • gui.PIVOT_SW
  • gui.PIVOT_W
  • gui.PIVOT_NW
### gui.get_position *Type:* FUNCTION Returns the position of the supplied node. **Parameters** - `node` (node) - node to get the position from **Returns** - `position` (vector3) - node position ### gui.get_rotation *Type:* FUNCTION Returns the rotation of the supplied node. The rotation is expressed as a quaternion **Parameters** - `node` (node) - node to get the rotation from **Returns** - `rotation` (quaternion) - node rotation ### gui.get_scale *Type:* FUNCTION Returns the scale of the supplied node. **Parameters** - `node` (node) - node to get the scale from **Returns** - `scale` (vector3) - node scale ### gui.get_screen_position *Type:* FUNCTION Returns the screen position of the supplied node. This function returns the calculated transformed position of the node, taking into account any parent node transforms. **Parameters** - `node` (node) - node to get the screen position from **Returns** - `position` (vector3) - node screen position ### gui.get_shadow *Type:* FUNCTION Returns the shadow color of the supplied node. See gui.get_color for info how vectors encode color values. **Parameters** - `node` (node) - node to get the shadow color from **Returns** - `color` (vector4) - node shadow color ### gui.get_size *Type:* FUNCTION Returns the size of the supplied node. **Parameters** - `node` (node) - node to get the size from **Returns** - `size` (vector3) - node size ### gui.get_size_mode *Type:* FUNCTION Returns the size of a node. The size mode defines how the node will adjust itself in size. Automatic size mode alters the node size based on the node's content. Automatic size mode works for Box nodes and Pie nodes which will both adjust their size to match the assigned image. Particle fx and Text nodes will ignore any size mode setting. **Parameters** - `node` (node) - node from which to get the size mode (node) **Returns** - `size_mode` (constant) - the current size mode
  • gui.SIZE_MODE_MANUAL
  • gui.SIZE_MODE_AUTO
### gui.get_slice9 *Type:* FUNCTION Returns the slice9 configuration values for the node. **Parameters** - `node` (node) - node to manipulate **Returns** - `values` (vector4) - configuration values ### gui.get_text *Type:* FUNCTION Returns the text value of a text node. This is only useful for text nodes. **Parameters** - `node` (node) - node from which to get the text **Returns** - `text` (string) - text value ### gui.get_texture *Type:* FUNCTION Returns the texture of a node. This is currently only useful for box or pie nodes. The texture must be mapped to the gui scene in the gui editor. **Parameters** - `node` (node) - node to get texture from **Returns** - `texture` (hash) - texture id ### gui.get_tracking *Type:* FUNCTION Returns the tracking value of a text node. **Parameters** - `node` (node) - node from where to get the tracking **Returns** - `tracking` (number) - tracking scaling number (default=0) ### gui.get_tree *Type:* FUNCTION Get a node and all its children as a Lua table. **Parameters** - `node` (node) - root node to get node tree from **Returns** - `clones` (table) - a table mapping node ids to the corresponding nodes ### gui.get_type *Type:* FUNCTION gets the node type **Parameters** - `node` (node) - node from which to get the type **Returns** - `type` (constant) - type
  • gui.TYPE_BOX
  • gui.TYPE_TEXT
  • gui.TYPE_PIE
  • gui.TYPE_PARTICLEFX
  • gui.TYPE_CUSTOM
- `subtype` (number | nil) - id of the custom type ### gui.get_visible *Type:* FUNCTION Returns true if a node is visible and false if it's not. Invisible nodes are not rendered. **Parameters** - `node` (node) - node to query **Returns** - `visible` (boolean) - whether the node is visible or not ### gui.get_width *Type:* FUNCTION Returns the scene width. **Returns** - `width` (number) - scene width ### gui.get_xanchor *Type:* FUNCTION The x-anchor specifies how the node is moved when the game is run in a different resolution. **Parameters** - `node` (node) - node to get x-anchor from **Returns** - `anchor` (constant) - anchor constant
  • gui.ANCHOR_NONE
  • gui.ANCHOR_LEFT
  • gui.ANCHOR_RIGHT
### gui.get_yanchor *Type:* FUNCTION The y-anchor specifies how the node is moved when the game is run in a different resolution. **Parameters** - `node` (node) - node to get y-anchor from **Returns** - `anchor` (constant) - anchor constant
  • gui.ANCHOR_NONE
  • gui.ANCHOR_TOP
  • gui.ANCHOR_BOTTOM
### gui.hide_keyboard *Type:* FUNCTION Hides the on-display touch keyboard on the device. ### gui.is_enabled *Type:* FUNCTION Returns true if a node is enabled and false if it's not. Disabled nodes are not rendered and animations acting on them are not evaluated. **Parameters** - `node` (node) - node to query - `recursive` (boolean) (optional) - check hierarchy recursively **Returns** - `enabled` (boolean) - whether the node is enabled or not ### gui.KEYBOARD_TYPE_DEFAULT *Type:* CONSTANT default keyboard ### gui.KEYBOARD_TYPE_EMAIL *Type:* CONSTANT email keyboard ### gui.KEYBOARD_TYPE_NUMBER_PAD *Type:* CONSTANT number input keyboard ### gui.KEYBOARD_TYPE_PASSWORD *Type:* CONSTANT password keyboard ### gui.move_above *Type:* FUNCTION Alters the ordering of the two supplied nodes by moving the first node above the second. If the second argument is nil the first node is moved to the top. **Parameters** - `node` (node) - to move - `reference` (node | nil) - reference node above which the first node should be moved ### gui.move_below *Type:* FUNCTION Alters the ordering of the two supplied nodes by moving the first node below the second. If the second argument is nil the first node is moved to the bottom. **Parameters** - `node` (node) - to move - `reference` (node | nil) - reference node below which the first node should be moved ### gui.new_box_node *Type:* FUNCTION Dynamically create a new box node. **Parameters** - `pos` (vector3 | vector4) - node position - `size` (vector3) - node size **Returns** - `node` (node) - new box node ### gui.new_particlefx_node *Type:* FUNCTION Dynamically create a particle fx node. **Parameters** - `pos` (vector3 | vector4) - node position - `particlefx` (hash | string) - particle fx resource name **Returns** - `node` (node) - new particle fx node ### gui.new_pie_node *Type:* FUNCTION Dynamically create a new pie node. **Parameters** - `pos` (vector3 | vector4) - node position - `size` (vector3) - node size **Returns** - `node` (node) - new pie node ### gui.new_text_node *Type:* FUNCTION Dynamically create a new text node. **Parameters** - `pos` (vector3 | vector4) - node position - `text` (string) - node text **Returns** - `node` (node) - new text node ### gui.new_texture *Type:* FUNCTION Dynamically create a new texture. **Parameters** - `texture_id` (string | hash) - texture id - `width` (number) - texture width - `height` (number) - texture height - `type` (string | constant) - texture type
  • "rgb" - RGB
  • "rgba" - RGBA
  • "l" - LUMINANCE
  • "astc" - ASTC compressed format
- `buffer` (string) - texture data - `flip` (boolean) - flip texture vertically **Returns** - `success` (boolean) - texture creation was successful - `code` (number) - one of the gui.RESULT_* codes if unsuccessful **Examples** How to create a texture and apply it to a new box node: ``` function init(self) local w = 200 local h = 300 -- A nice orange. String with the RGB values. local orange = string.char(0xff) .. string.char(0x80) .. string.char(0x10) -- Create the texture. Repeat the color string for each pixel. local ok, reason = gui.new_texture("orange_tx", w, h, "rgb", string.rep(orange, w * h)) if ok then -- Create a box node and apply the texture to it. local n = gui.new_box_node(vmath.vector3(200, 200, 0), vmath.vector3(w, h, 0)) gui.set_texture(n, "orange_tx") else -- Could not create texture for some reason... if reason == gui.RESULT_TEXTURE_ALREADY_EXISTS then ... else ... end end end ```How to create a texture using .astc format ```lua local path = "/assets/images/logo_4x4.astc" local buffer = sys.load_resource(path) local n = gui.new_box_node(pos, vmath.vector3(size, size, 0)) -- size is read from the .astc buffer -- flip is not supported gui.new_texture(path, 0, 0, "astc", buffer, false) gui.set_texture(n, path) ``` ### gui.pick_node *Type:* FUNCTION Tests whether a coordinate is within the bounding box of a node. **Parameters** - `node` (node) - node to be tested for picking - `x` (number) - x-coordinate (see on_input ) - `y` (number) - y-coordinate (see on_input ) **Returns** - `pickable` (boolean) - pick result ### gui.PIEBOUNDS_ELLIPSE *Type:* CONSTANT elliptical pie node bounds ### gui.PIEBOUNDS_RECTANGLE *Type:* CONSTANT rectangular pie node bounds ### gui.PIVOT_CENTER *Type:* CONSTANT center pivot ### gui.PIVOT_E *Type:* CONSTANT east pivot ### gui.PIVOT_N *Type:* CONSTANT north pivot ### gui.PIVOT_NE *Type:* CONSTANT north-east pivot ### gui.PIVOT_NW *Type:* CONSTANT north-west pivot ### gui.PIVOT_S *Type:* CONSTANT south pivot ### gui.PIVOT_SE *Type:* CONSTANT south-east pivot ### gui.PIVOT_SW *Type:* CONSTANT south-west pivot ### gui.PIVOT_W *Type:* CONSTANT west pivot ### gui.play_flipbook *Type:* FUNCTION Play flipbook animation on a box or pie node. The current node texture must contain the animation. Use this function to set one-frame still images on the node. **Parameters** - `node` (node) - node to set animation for - `animation` (string | hash) - animation id - `complete_function` (function(self, node)) (optional) - optional function to call when the animation has completed
self
object The current object.
node
node The node that is animated.
- `play_properties` (table) (optional) - optional table with properties
offset
number The normalized initial value of the animation cursor when the animation starts playing
playback_rate
number The rate with which the animation will be played. Must be positive
**Examples** Set the texture of a node to a flipbook animation from an atlas: ``` local function anim_callback(self, node) -- Take action after animation has played. end function init(self) -- Create a new node and set the texture to a flipbook animation local node = gui.get_node("button_node") gui.set_texture(node, "gui_sprites") gui.play_flipbook(node, "animated_button") end ``` Set the texture of a node to an image from an atlas: ``` -- Create a new node and set the texture to a "button.png" from atlas local node = gui.get_node("button_node") gui.set_texture(node, "gui_sprites") gui.play_flipbook(node, "button") ``` ### gui.play_particlefx *Type:* FUNCTION Plays the paricle fx for a gui node **Parameters** - `node` (node) - node to play particle fx for - `emitter_state_function` (function(self, node, emitter, state)) (optional) - optional callback function that will be called when an emitter attached to this particlefx changes state.
self
object The current object
node
hash The particle fx node, or nil if the node was deleted
emitter
hash The id of the emitter
state
constant the new state of the emitter:
  • particlefx.EMITTER_STATE_SLEEPING
  • particlefx.EMITTER_STATE_PRESPAWN
  • particlefx.EMITTER_STATE_SPAWNING
  • particlefx.EMITTER_STATE_POSTSPAWN
**Examples** How to play a particle fx when a gui node is created. The callback receives the gui node, the hash of the id of the emitter, and the new state of the emitter as particlefx.EMITTER_STATE_. ``` local function emitter_state_change(self, node, emitter, state) if emitter == hash("exhaust") and state == particlefx.EMITTER_STATE_POSTSPAWN then -- exhaust is done spawning particles... end end function init(self) gui.play_particlefx(gui.get_node("particlefx"), emitter_state_change) end ``` ### gui.PLAYBACK_LOOP_BACKWARD *Type:* CONSTANT loop backward ### gui.PLAYBACK_LOOP_FORWARD *Type:* CONSTANT loop forward ### gui.PLAYBACK_LOOP_PINGPONG *Type:* CONSTANT ping pong loop ### gui.PLAYBACK_ONCE_BACKWARD *Type:* CONSTANT once backward ### gui.PLAYBACK_ONCE_FORWARD *Type:* CONSTANT once forward ### gui.PLAYBACK_ONCE_PINGPONG *Type:* CONSTANT once forward and then backward ### gui.PROP_COLOR *Type:* CONSTANT color property ### gui.PROP_EULER *Type:* CONSTANT euler property ### gui.PROP_FILL_ANGLE *Type:* CONSTANT fill_angle property ### gui.PROP_INNER_RADIUS *Type:* CONSTANT inner_radius property ### gui.PROP_LEADING *Type:* CONSTANT leading property ### gui.PROP_OUTLINE *Type:* CONSTANT outline color property ### gui.PROP_POSITION *Type:* CONSTANT position property ### gui.PROP_ROTATION *Type:* CONSTANT rotation property ### gui.PROP_SCALE *Type:* CONSTANT scale property ### gui.PROP_SHADOW *Type:* CONSTANT shadow color property ### gui.PROP_SIZE *Type:* CONSTANT size property ### gui.PROP_SLICE9 *Type:* CONSTANT slice9 property ### gui.PROP_TRACKING *Type:* CONSTANT tracking property ### gui.reset_keyboard *Type:* FUNCTION Resets the input context of keyboard. This will clear marked text. ### gui.reset_material *Type:* FUNCTION Resets the node material to the material assigned in the gui scene. **Parameters** - `node` (node) - node to reset the material for **Examples** Resetting the material for a node: ``` local node = gui.get_node("my_node") gui.reset_material(node) ``` ### gui.reset_nodes *Type:* FUNCTION Resets all nodes in the current GUI scene to their initial state. The reset only applies to static node loaded from the scene. Nodes that are created dynamically from script are not affected. ### gui.RESULT_DATA_ERROR *Type:* CONSTANT The provided data is not in the expected format or is in some other way incorrect, for instance the image data provided to gui.new_texture(). ### gui.RESULT_OUT_OF_RESOURCES *Type:* CONSTANT The system is out of resources, for instance when trying to create a new texture using gui.new_texture(). ### gui.RESULT_TEXTURE_ALREADY_EXISTS *Type:* CONSTANT The texture id already exists when trying to use gui.new_texture(). ### gui.SAFE_AREA_BOTH *Type:* CONSTANT Safe area mode that applies insets on all edges. ### gui.SAFE_AREA_LONG *Type:* CONSTANT Safe area mode that applies insets only on the long edges. ### gui.SAFE_AREA_NONE *Type:* CONSTANT Safe area mode that ignores safe area insets. ### gui.SAFE_AREA_SHORT *Type:* CONSTANT Safe area mode that applies insets only on the short edges. ### gui.screen_to_local *Type:* FUNCTION Convert the screen position to the local position of supplied node **Parameters** - `node` (node) - node used for getting local transformation matrix - `screen_position` (vector3) - screen position **Returns** - `local_position` (vector3) - local position ### gui.set *Type:* FUNCTION Instead of using specific setteres such as gui.set_position or gui.set_scale, you can use gui.set instead and supply the property as a string or a hash. While this function is similar to go.get and go.set, there are a few more restrictions when operating in the gui namespace. Most notably, only these named properties identifiers are supported: "position" "rotation" "euler" "scale" "color" "outline" "shadow" "size" "fill_angle" (pie) "inner_radius" (pie) "leading" (text) "tracking" (text) "slice9" (slice9) The value to set must either be a vmath.vector4, vmath.vector3, vmath.quat or a single number and depends on the property name you want to set. I.e when setting the "position" property, you need to use a vmath.vector4 and when setting a single component of the property, such as "position.x", you need to use a single value. Note: When setting the rotation using the "rotation" property, you need to pass in a vmath.quat. This behaviour is different than from the gui.set_rotation function, the intention is to move new functionality closer to go namespace so that migrating between gui and go is easier. To set the rotation using degrees instead, use the "euler" property instead. The rotation and euler properties are linked, changing one of them will change the backing data of the other. Similar to go.set, you can also use gui.set for setting material constant values on a node. E.g if a material has specified a constant called tint in the .material file, you can use gui.set to set the value of that constant by calling gui.set(node, "tint", vmath.vec4(1,0,0,1)), or gui.set(node, "matrix", vmath.matrix4()) if the constant is a matrix. Arrays are also supported by gui.set - to set an array constant, you need to pass in an options table with the 'index' key set. If the material has a constant array called 'tint_array' specified in the material, you can use gui.set(node, "tint_array", vmath.vec4(1,0,0,1), { index = 4}) to set the fourth array element to a different value. **Parameters** - `node` (node | url) - node to set the property for, or msg.url() to the gui itself - `property` (string | hash | constant) - the property to set - `value` (number | vector4 | vector3 | quaternion) - the property to set - `options` (table) (optional) - optional options table (only applicable for material constants) - index number index into array property (1 based) - key hash name of internal property **Examples** Updates the position property on an existing node: ``` local node = gui.get_node("my_box_node") local node_position = gui.get(node, "position") gui.set(node, "position.x", node_position.x + 128) ``` Updates the rotation property on an existing node: ``` local node = gui.get_node("my_box_node") gui.set(node, "rotation", vmath.quat_rotation_z(math.rad(45))) -- this is equivalent to: gui.set(node, "euler.z", 45) -- or using the entire vector: gui.set(node, "euler", vmath.vector3(0,0,45)) -- or using the set_rotation gui.set_rotation(node, vmath.vector3(0,0,45)) ``` Sets various material constants for a node: ``` local node = gui.get_node("my_box_node") gui.set(node, "tint", vmath.vector4(1,0,0,1)) -- matrix4 is also supported gui.set(node, "light_matrix", vmath.matrix4()) -- update a constant in an array at position 4. the array is specified in the shader as: -- uniform vec4 tint_array[4]; // lua is 1 based, shader is 0 based gui.set(node, "tint_array", vmath.vector4(1,0,0,1), { index = 4 }) -- update a matrix constant in an array at position 4. the array is specified in the shader as: -- uniform mat4 light_matrix_array[4]; gui.set(node, "light_matrix_array", vmath.matrix4(), { index = 4 }) -- update a sub-element in a constant gui.set(node, "tint.x", 1) -- update a sub-element in an array constant at position 4 gui.set(node, "tint_array.x", 1, {index = 4}) ``` Set a named property ``` function on_message(self, message_id, message, sender) if message_id == hash("set_font") then gui.set(msg.url(), "fonts", message.font, {key = "my_font_name"}) gui.set_font(gui.get_node("text"), "my_font_name") elseif message_id == hash("set_texture") then gui.set(msg.url(), "textures", message.texture, {key = "my_texture"}) gui.set_texture(gui.get_node("box"), "my_texture") gui.play_flipbook(gui.get_node("box"), "logo_256") end end ``` ### gui.set_adjust_mode *Type:* FUNCTION Sets the adjust mode on a node. The adjust mode defines how the node will adjust itself to screen resolutions that differs from the one in the project settings. **Parameters** - `node` (node) - node to set adjust mode for - `adjust_mode` (constant) - adjust mode to set
  • gui.ADJUST_FIT
  • gui.ADJUST_ZOOM
  • gui.ADJUST_STRETCH
### gui.set_alpha *Type:* FUNCTION sets the node alpha **Parameters** - `node` (node) - node for which to set alpha - `alpha` (number) - 0..1 alpha color ### gui.set_blend_mode *Type:* FUNCTION Set the blend mode of a node. Blend mode defines how the node will be blended with the background. **Parameters** - `node` (node) - node to set blend mode for - `blend_mode` (constant) - blend mode to set
  • gui.BLEND_ALPHA
  • gui.BLEND_ADD
  • gui.BLEND_ADD_ALPHA
  • gui.BLEND_MULT
  • gui.BLEND_SCREEN
### gui.set_clipping_inverted *Type:* FUNCTION If node is set as an inverted clipping node, it will clip anything inside as opposed to outside. **Parameters** - `node` (node) - node to set clipping inverted state for - `inverted` (boolean) - true or false ### gui.set_clipping_mode *Type:* FUNCTION Clipping mode defines how the node will clip it's children nodes **Parameters** - `node` (node) - node to set clipping mode for - `clipping_mode` (constant) - clipping mode to set
  • gui.CLIPPING_MODE_NONE
  • gui.CLIPPING_MODE_STENCIL
### gui.set_clipping_visible *Type:* FUNCTION If node is set as an visible clipping node, it will be shown as well as clipping. Otherwise, it will only clip but not show visually. **Parameters** - `node` (node) - node to set clipping visibility for - `visible` (boolean) - true or false ### gui.set_color *Type:* FUNCTION Sets the color of the supplied node. The components of the supplied vector3 or vector4 should contain the color channel values: Component Color value x Red value y Green value z Blue value w vector4 Alpha value **Parameters** - `node` (node) - node to set the color for - `color` (vector3 | vector4) - new color ### gui.set_enabled *Type:* FUNCTION Sets a node to the disabled or enabled state. Disabled nodes are not rendered and animations acting on them are not evaluated. **Parameters** - `node` (node) - node to be enabled/disabled - `enabled` (boolean) - whether the node should be enabled or not ### gui.set_euler *Type:* FUNCTION Sets the rotation of the supplied node. The rotation is expressed in degree Euler angles. **Parameters** - `node` (node) - node to set the rotation for - `rotation` (vector3 | vector4) - new rotation ### gui.set_fill_angle *Type:* FUNCTION Set the sector angle of a pie node. **Parameters** - `node` (node) - node to set the fill angle for - `angle` (number) - sector angle ### gui.set_flipbook_cursor *Type:* FUNCTION This is only useful nodes with flipbook animations. The cursor is normalized. **Parameters** - `node` (node) - node to set the cursor for - `cursor` (number) - cursor value ### gui.set_flipbook_playback_rate *Type:* FUNCTION This is only useful nodes with flipbook animations. Sets the playback rate of the flipbook animation on a node. Must be positive. **Parameters** - `node` (node) - node to set the cursor for - `playback_rate` (number) - playback rate ### gui.set_font *Type:* FUNCTION This is only useful for text nodes. The font must be mapped to the gui scene in the gui editor. **Parameters** - `node` (node) - node for which to set the font - `font` (string | hash) - font id ### gui.set_id *Type:* FUNCTION Set the id of the specicied node to a new value. Nodes created with the gui.new_*_node() functions get an empty id. This function allows you to give dynamically created nodes an id. No checking is done on the uniqueness of supplied ids. It is up to you to make sure you use unique ids. **Parameters** - `node` (node) - node to set the id for - `id` (string | hash) - id to set **Examples** Create a new node and set its id: ``` local pos = vmath.vector3(100, 100, 0) local size = vmath.vector3(100, 100, 0) local node = gui.new_box_node(pos, size) gui.set_id(node, "my_new_node") ``` ### gui.set_inherit_alpha *Type:* FUNCTION sets the node inherit alpha state **Parameters** - `node` (node) - node from which to set the inherit alpha state - `inherit_alpha` (boolean) - true or false ### gui.set_inner_radius *Type:* FUNCTION Sets the inner radius of a pie node. The radius is defined along the x-axis. **Parameters** - `node` (node) - node to set the inner radius for - `radius` (number) - inner radius ### gui.set_layer *Type:* FUNCTION The layer must be mapped to the gui scene in the gui editor. **Parameters** - `node` (node) - node for which to set the layer - `layer` (string | hash) - layer id ### gui.set_layout *Type:* FUNCTION Applies a named layout on the GUI scene. This re-applies per-layout node descriptors and, if a matching Display Profile exists, updates the scene resolution. Emits the "layout_changed" message to the scene script when the layout actually changes. **Parameters** - `layout` (string | hash) - the layout id to apply **Returns** - `return` (boolean) - true if the layout exists in the scene and was applied, false otherwise ### gui.set_leading *Type:* FUNCTION Sets the leading value for a text node. This value is used to scale the line spacing of text. **Parameters** - `node` (node) - node for which to set the leading - `leading` (number) - a scaling value for the line spacing (default=1) ### gui.set_line_break *Type:* FUNCTION Sets the line-break mode on a text node. This is only useful for text nodes. **Parameters** - `node` (node) - node to set line-break for - `line_break` (boolean) - true or false ### gui.set_material *Type:* FUNCTION Set the material on a node. The material must be mapped to the gui scene in the gui editor, and assigning a material is supported for all node types. To set the default material that is assigned to the gui scene node, use gui.reset_material(node_id) instead. **Parameters** - `node` (node) - node to set material for - `material` (string | hash) - material id **Examples** Assign an existing material to a node: ``` local node = gui.get_node("my_node") gui.set_material(node, "my_material") ``` ### gui.set_outer_bounds *Type:* FUNCTION Sets the outer bounds mode for a pie node. **Parameters** - `node` (node) - node for which to set the outer bounds mode - `bounds_mode` (constant) - the outer bounds mode of the pie node:
  • gui.PIEBOUNDS_RECTANGLE
  • gui.PIEBOUNDS_ELLIPSE
### gui.set_outline *Type:* FUNCTION Sets the outline color of the supplied node. See gui.set_color for info how vectors encode color values. **Parameters** - `node` (node) - node to set the outline color for - `color` (vector3 | vector4) - new outline color ### gui.set_parent *Type:* FUNCTION Sets the parent node of the specified node. **Parameters** - `node` (node) - node for which to set its parent - `parent` (node) (optional) - parent node to set, pass nil to remove parent - `keep_scene_transform` (boolean) (optional) - optional flag to make the scene position being perserved ### gui.set_particlefx *Type:* FUNCTION Set the paricle fx for a gui node **Parameters** - `node` (node) - node to set particle fx for - `particlefx` (hash | string) - particle fx id ### gui.set_perimeter_vertices *Type:* FUNCTION Sets the number of generated vertices around the perimeter of a pie node. **Parameters** - `node` (node) - pie node - `vertices` (number) - vertex count ### gui.set_pivot *Type:* FUNCTION The pivot specifies how the node is drawn and rotated from its position. **Parameters** - `node` (node) - node to set pivot for - `pivot` (constant) - pivot constant
  • gui.PIVOT_CENTER
  • gui.PIVOT_N
  • gui.PIVOT_NE
  • gui.PIVOT_E
  • gui.PIVOT_SE
  • gui.PIVOT_S
  • gui.PIVOT_SW
  • gui.PIVOT_W
  • gui.PIVOT_NW
### gui.set_position *Type:* FUNCTION Sets the position of the supplied node. **Parameters** - `node` (node) - node to set the position for - `position` (vector3 | vector4) - new position ### gui.set_render_order *Type:* FUNCTION Set the order number for the current GUI scene. The number dictates the sorting of the "gui" render predicate, in other words in which order the scene will be rendered in relation to other currently rendered GUI scenes. The number must be in the range 0 to 15. **Parameters** - `order` (number) - rendering order (0-15) ### gui.set_rotation *Type:* FUNCTION Sets the rotation of the supplied node. The rotation is expressed as a quaternion **Parameters** - `node` (node) - node to set the rotation for - `rotation` (quaternion | vector4) - new rotation ### gui.set_safe_area_mode *Type:* FUNCTION Sets how the safe area is applied to this gui scene. **Parameters** - `mode` (constant) - safe area mode
  • gui.SAFE_AREA_NONE
  • gui.SAFE_AREA_LONG
  • gui.SAFE_AREA_SHORT
  • gui.SAFE_AREA_BOTH
### gui.set_scale *Type:* FUNCTION Sets the scaling of the supplied node. **Parameters** - `node` (node) - node to set the scale for - `scale` (vector3 | vector4) - new scale ### gui.set_screen_position *Type:* FUNCTION Set the screen position to the supplied node **Parameters** - `node` (node) - node to set the screen position to - `screen_position` (vector3) - screen position ### gui.set_shadow *Type:* FUNCTION Sets the shadow color of the supplied node. See gui.set_color for info how vectors encode color values. **Parameters** - `node` (node) - node to set the shadow color for - `color` (vector3 | vector4) - new shadow color ### gui.set_size *Type:* FUNCTION Sets the size of the supplied node. You can only set size on nodes with size mode set to SIZE_MODE_MANUAL **Parameters** - `node` (node) - node to set the size for - `size` (vector3 | vector4) - new size ### gui.set_size_mode *Type:* FUNCTION Sets the size mode of a node. The size mode defines how the node will adjust itself in size. Automatic size mode alters the node size based on the node's content. Automatic size mode works for Box nodes and Pie nodes which will both adjust their size to match the assigned image. Particle fx and Text nodes will ignore any size mode setting. **Parameters** - `node` (node) - node to set size mode for - `size_mode` (constant) - size mode to set
  • gui.SIZE_MODE_MANUAL
  • gui.SIZE_MODE_AUTO
### gui.set_slice9 *Type:* FUNCTION Set the slice9 configuration values for the node. **Parameters** - `node` (node) - node to manipulate - `values` (vector4) - new values ### gui.set_text *Type:* FUNCTION Set the text value of a text node. This is only useful for text nodes. **Parameters** - `node` (node) - node to set text for - `text` (string | number) - text to set ### gui.set_texture *Type:* FUNCTION Set the texture on a box or pie node. The texture must be mapped to the gui scene in the gui editor. The function points out which texture the node should render from. If the texture is an atlas, further information is needed to select which image/animation in the atlas to render. In such cases, use gui.play_flipbook() in addition to this function. **Parameters** - `node` (node) - node to set texture for - `texture` (string | hash) - texture id **Examples** To set a texture (or animation) from an atlas: ``` local node = gui.get_node("box_node") gui.set_texture(node, "my_atlas") gui.play_flipbook(node, "image") ``` Set a dynamically created texture to a node. Note that there is only one texture image in this case so gui.set_texture() is sufficient. ``` local w = 200 local h = 300 -- A nice orange. String with the RGB values. local orange = string.char(0xff) .. string.char(0x80) .. string.char(0x10) -- Create the texture. Repeat the color string for each pixel. if gui.new_texture("orange_tx", w, h, "rgb", string.rep(orange, w * h)) then local node = gui.get_node("box_node") gui.set_texture(node, "orange_tx") end ``` ### gui.set_texture_data *Type:* FUNCTION Set the texture buffer data for a dynamically created texture. **Parameters** - `texture` (string | hash) - texture id - `width` (number) - texture width - `height` (number) - texture height - `type` (string | constant) - texture type
  • "rgb" - RGB
  • "rgba" - RGBA
  • "l" - LUMINANCE
  • "astc" - ASTC compressed format
- `buffer` (string) - texture data - `flip` (boolean) - flip texture vertically **Returns** - `success` (boolean) - setting the data was successful **Examples** ``` function init(self) local w = 200 local h = 300 -- Create a dynamic texture, all white. if gui.new_texture("dynamic_tx", w, h, "rgb", string.rep(string.char(0xff), w * h * 3)) then -- Create a box node and apply the texture to it. local n = gui.new_box_node(vmath.vector3(200, 200, 0), vmath.vector3(w, h, 0)) gui.set_texture(n, "dynamic_tx") ... -- Change the data in the texture to a nice orange. local orange = string.char(0xff) .. string.char(0x80) .. string.char(0x10) if gui.set_texture_data("dynamic_tx", w, h, "rgb", string.rep(orange, w * h)) then -- Go on and to more stuff ... end else -- Something went wrong ... end end ``` ### gui.set_tracking *Type:* FUNCTION Sets the tracking value of a text node. This value is used to adjust the vertical spacing of characters in the text. **Parameters** - `node` (node) - node for which to set the tracking - `tracking` (number) - a scaling number for the letter spacing (default=0) ### gui.set_visible *Type:* FUNCTION Set if a node should be visible or not. Only visible nodes are rendered. **Parameters** - `node` (node) - node to be visible or not - `visible` (boolean) - whether the node should be visible or not ### gui.set_xanchor *Type:* FUNCTION The x-anchor specifies how the node is moved when the game is run in a different resolution. **Parameters** - `node` (node) - node to set x-anchor for - `anchor` (constant) - anchor constant
  • gui.ANCHOR_NONE
  • gui.ANCHOR_LEFT
  • gui.ANCHOR_RIGHT
### gui.set_yanchor *Type:* FUNCTION The y-anchor specifies how the node is moved when the game is run in a different resolution. **Parameters** - `node` (node) - node to set y-anchor for - `anchor` (constant) - anchor constant
  • gui.ANCHOR_NONE
  • gui.ANCHOR_TOP
  • gui.ANCHOR_BOTTOM
### gui.show_keyboard *Type:* FUNCTION Shows the on-display touch keyboard. The specified type of keyboard is displayed if it is available on the device. This function is only available on iOS and Android. . **Parameters** - `type` (constant) - keyboard type
  • gui.KEYBOARD_TYPE_DEFAULT
  • gui.KEYBOARD_TYPE_EMAIL
  • gui.KEYBOARD_TYPE_NUMBER_PAD
  • gui.KEYBOARD_TYPE_PASSWORD
- `autoclose` (boolean) - if the keyboard should automatically close when clicking outside ### gui.SIZE_MODE_AUTO *Type:* CONSTANT The size of the node is determined by the currently assigned texture. ### gui.SIZE_MODE_MANUAL *Type:* CONSTANT The size of the node is determined by the size set in the editor, the constructor or by gui.set_size() ### gui.stop_particlefx *Type:* FUNCTION Stops the particle fx for a gui node **Parameters** - `node` (node) - node to stop particle fx for - `options` (table) (optional) - options when stopping the particle fx. Supported options:
  • boolean clear: instantly clear spawned particles
### gui.TYPE_BOX *Type:* CONSTANT box type ### gui.TYPE_CUSTOM *Type:* CONSTANT custom type ### gui.TYPE_PARTICLEFX *Type:* CONSTANT particlefx type ### gui.TYPE_PIE *Type:* CONSTANT pie type ### gui.TYPE_TEXT *Type:* CONSTANT text type ### init *Type:* FUNCTION This is a callback-function, which is called by the engine when a gui component is initialized. It can be used to set the initial state of the script and gui scene. **Parameters** - `self` (userdata) - reference to the script state to be used for storing data **Examples** ``` function init(self) -- set up useful data self.my_value = 1 end ``` ### layout_changed *Type:* MESSAGE This message is broadcast to every GUI component when a layout change has been initiated on device. **Parameters** - `id` (hash) - the id of the layout the engine is changing to - `previous_id` (hash) - the id of the layout the engine is changing from **Examples** ``` function on_message(self, message_id, message, sender) if message_id == hash("layout_changed") and message.id == hash("Landscape") then -- switching layout to "Landscape"... ... end end ``` ### material *Type:* PROPERTY The main material (the default material assigned to a GUI) used when rendering the gui. The type of the property is hash. **Examples** How to set material using a script property (see resource.material) ``` go.property("desaturate_material", resource.material("/desaturate.material")) function init(self) go.set("#gui", "material", self.desaturate_material) end ``` ### materials *Type:* PROPERTY The materials used when rendering the gui. The type of the property is hash. Key must be specified in options table. **Examples** How to change a named material resource using a script property from a script ``` go.property("my_material", resource.material("/my_material.material")) function init(self) -- this will update the "my_gui_material" entry in the GUI to use the material -- specified in the "my_material" script property. go.set("#gui", "materials", self.my_material, { key = "my_gui_material" }) end ``` ### on_input *Type:* FUNCTION This is a callback-function, which is called by the engine when user input is sent to the instance of the gui component. It can be used to take action on the input, e.g. modify the gui according to the input. For an instance to obtain user input, it must first acquire input focus through the message acquire_input_focus. Any instance that has obtained input will be put on top of an input stack. Input is sent to all listeners on the stack until the end of stack is reached, or a listener returns true to signal that it wants input to be consumed. See the documentation of acquire_input_focus for more information. The action parameter is a table containing data about the input mapped to the action_id. For mapped actions it specifies the value of the input and if it was just pressed or released. Actions are mapped to input in an input_binding-file. Mouse movement is specifically handled and uses nil as its action_id. The action only contains positional parameters in this case, such as x and y of the pointer. Here is a brief description of the available table fields: Field Description value The amount of input given by the user. This is usually 1 for buttons and 0-1 for analogue inputs. This is not present for mouse movement and text input. pressed If the input was pressed this frame. This is not present for mouse movement and text input. released If the input was released this frame. This is not present for mouse movement and text input. repeated If the input was repeated this frame. This is similar to how a key on a keyboard is repeated when you hold it down. This is not present for mouse movement and text input. x The x value of a pointer device, if present. This is not present for gamepad, key and text input. y The y value of a pointer device, if present. This is not present for gamepad, key and text input. screen_x The screen space x value of a pointer device, if present. This is not present for gamepad, key and text input. screen_y The screen space y value of a pointer device, if present. This is not present for gamepad, key and text input. dx The change in x value of a pointer device, if present. This is not present for gamepad, key and text input. dy The change in y value of a pointer device, if present. This is not present for gamepad, key and text input. screen_dx The change in screen space x value of a pointer device, if present. This is not present for gamepad, key and text input. screen_dy The change in screen space y value of a pointer device, if present. This is not present for gamepad, key and text input. gamepad The index of the gamepad device that provided the input. See table below about gamepad input. touch List of touch input, one element per finger, if present. See table below about touch input text Text input from a (virtual) keyboard or similar. marked_text Sequence of entered symbols while entering a symbol combination, for example Japanese Kana. Gamepad specific fields: Field Description gamepad The index of the gamepad device that provided the input. userid Id of the user associated with the controller. Usually only relevant on consoles. gamepad_unknown True if the inout originated from an unknown/unmapped gamepad. gamepad_name Name of the gamepad gamepad_axis List of gamepad axis values. For raw gamepad input only. gamepadhats List of gamepad hat values. For raw gamepad input only. gamepad_buttons List of gamepad button values. For raw gamepad input only. Touch input table: Field Description id A number identifying the touch input during its duration. pressed True if the finger was pressed this frame. released True if the finger was released this frame. tap_count Number of taps, one for single, two for double-tap, etc x The x touch location. y The y touch location. dx The change in x value. dy The change in y value. acc_x Accelerometer x value (if present). acc_y Accelerometer y value (if present). acc_z Accelerometer z value (if present). **Parameters** - `self` (userdata) - reference to the script state to be used for storing data - `action_id` (hash) - id of the received input action, as mapped in the input_binding-file - `action` (table) - a table containing the input data, see above for a description **Returns** - `consume` (boolean | nil) - optional boolean to signal if the input should be consumed (not passed on to others) or not, default is false **Examples** ``` function on_input(self, action_id, action) -- check for input if action_id == hash("my_action") then -- take appropritate action self.my_value = action.value end -- consume input return true end ``` ### on_message *Type:* FUNCTION This is a callback-function, which is called by the engine whenever a message has been sent to the gui component. It can be used to take action on the message, e.g. update the gui or send a response back to the sender of the message. The message parameter is a table containing the message data. If the message is sent from the engine, the documentation of the message specifies which data is supplied. See the update function for examples on how to use this callback-function. **Parameters** - `self` (userdata) - reference to the script state to be used for storing data - `message_id` (hash) - id of the received message - `message` (table) - a table containing the message data ### on_reload *Type:* FUNCTION This is a callback-function, which is called by the engine when the gui script is reloaded, e.g. from the editor. It can be used for live development, e.g. to tweak constants or set up the state properly for the script. **Parameters** - `self` (userdata) - reference to the script state to be used for storing data **Examples** ``` function on_reload(self) -- restore some color (or similar) gui.set_color(gui.get_node("my_node"), self.my_original_color) end ``` ### textures *Type:* PROPERTY The textures used in the gui. The type of the property is hash. Key must be specified in options table. **Examples** How to set texture using a script property (see resource.atlas) ``` go.property("cards_red", resource.atlas("/cards_red.atlas")) go.property("cards_blue", resource.atlas("/cards_blue.atlas")) function init(self) go.set("#gui", "textures", self.cards_red, {key = "cards"}) end ``` ### update *Type:* FUNCTION This is a callback-function, which is called by the engine every frame to update the state of a gui component. It can be used to perform any kind of gui related tasks, e.g. animating nodes. **Parameters** - `self` (userdata) - reference to the script state to be used for storing data - `dt` (number) - the time-step of the frame update **Examples** This example demonstrates how to update a text node that displays game score in a counting fashion. It is assumed that the gui component receives messages from the game when a new score is to be shown. ``` function init(self) -- fetch the score text node for later use (assumes it is called "score") self.score_node = gui.get_node("score") -- keep track of the current score counted up so far self.current_score = 0 -- keep track of the target score we should count up to self.target_score = 0 -- how fast we will update the score, in score/second self.score_update_speed = 1 end function update(self, dt) -- check if target score is more than current score if self.current_score self.target_score then self.current_score = self.target_score end -- update the score text node gui.set_text(self.score_node, "" .. math.floor(self.current_score)) end end function on_message(self, message_id, message, sender) -- check the message if message_id == hash("set_score") then self.target_score = message.score end end ``` # HTML5 {#apis:html5-lua} **Namespace:** `html5` **Language:** Lua **Type:** Defold Lua **File:** `script_html5_js.cpp` **Source:** `engine/script/src/script_html5_js.cpp` HTML5 platform specific functions. [icon:html5] The following functions are only available on HTML5 builds, the `html5.*` Lua namespace will not be available on other platforms. ## API ### html5.run *Type:* FUNCTION Executes the supplied string as JavaScript inside the browser. A call to this function is blocking, the result is returned as-is, as a string. (Internally this will execute the string using the eval() JavaScript function.) **Parameters** - `code` (string) - Javascript code to run **Returns** - `result` (string) - result as string **Examples** ``` local res = html5.run("10 + 20") -- returns the string "30" print(res) local res_num = tonumber(res) -- convert to number print(res_num - 20) -- prints 10 ``` ### html5.set_interaction_listener *Type:* FUNCTION Set a JavaScript interaction listener callaback from lua that will be invoked when a user interacts with the web page by clicking, touching or typing. The callback can then call DOM restricted actions like requesting a pointer lock, or start playing sounds the first time the callback is invoked. **Parameters** - `callback` (function(self) | nil) - The interaction callback. Pass an empty function or nil if you no longer wish to receive callbacks.
self
object The calling script
**Examples** ``` local function on_interaction(self) print("on_interaction called") html5.set_interaction_listener(nil) end function init(self) html5.set_interaction_listener(on_interaction) end ``` # HTTP {#apis:http-lua} **Namespace:** `http` **Language:** Lua **Type:** Defold Lua **File:** `script_http.cpp` **Source:** `engine/gamesys/src/gamesys/scripts/script_http.cpp` Functions for performing HTTP and HTTPS requests. ## API ### http.request *Type:* FUNCTION Perform a HTTP/HTTPS request. If no timeout value is passed, the configuration value "network.http_timeout" is used. If that is not set, the timeout value is 0 (which blocks indefinitely). **Parameters** - `url` (string) - target url - `method` (string) - HTTP/HTTPS method, e.g. "GET", "PUT", "POST" etc. - `callback` (function(self, id, response)) - response callback function
self
object The script instance
id
hash Internal message identifier. Do not use!
response
table The response data. Contains the fields:
  • number status: the status of the response
  • string response: the response data (if not saved on disc)
  • table headers: all the returned headers (if status is 200 or 206)
  • string path: the stored path (if saved to disc)
  • string error: if any unforeseen errors occurred (e.g. file I/O)
  • number bytes_received: the amount of bytes received/sent for a request, only if option report_progress is true
  • number bytes_total: the total amount of bytes for a request, only if option report_progress is true
  • number range_start: the start offset into the requested file
  • number range_end: the end offset into the requested file (inclusive)
  • number document_size: the full size of the requested file
- `headers` (table) (optional) - optional table with custom headers - `post_data` (string) (optional) - optional data to send - `options` (table) (optional) - optional table with request parameters. Supported entries:
  • number timeout: timeout in seconds
  • string path: path on disc where to download the file. Only overwrites the path if status is 200. Path should be absolute
  • boolean ignore_cache: don't return cached data if we get a 304. Not available in HTML5 build
  • boolean chunked_transfer: use chunked transfer encoding for https requests larger than 16kb. Defaults to true. Not available in HTML5 build
  • boolean report_progress: when it is true, the amount of bytes sent and/or received for a request will be passed into the callback function
**Examples** Basic HTTP-GET request. The callback receives a table with the response in the fields status, the response (the data) and headers (a table). ``` local function http_result(self, _, response) if response.bytes_total ~= nil then update_my_progress_bar(self, response.bytes_received / response.bytes_total) else print(response.status) print(response.response) pprint(response.headers) end end function init(self) http.request("http://www.google.com", "GET", http_result, nil, nil, { report_progress = true }) end ``` # Image {#apis:image-lua} **Namespace:** `image` **Language:** Lua **Type:** Defold Lua **File:** `script_image.cpp` **Source:** `engine/gamesys/src/gamesys/scripts/script_image.cpp` Functions for creating image objects. ## API ### image.get_astc_header *Type:* FUNCTION get the header of an .astc buffer **Parameters** - `buffer` (string) - .astc file data buffer **Returns** - `table` (table | nil) - header or nil if buffer is not a valid .astc. The header has these fields:
  • number width: image width
  • number height: image height
  • number depth: image depth
  • number block_size_x: block size x
  • number block_size_y: block size y
  • number block_size_z: block size z
**Examples** How to get the block size and dimensions from a .astc file ``` local s = sys.load_resource("/assets/cat.astc") local header = image.get_astc_header(s) pprint(s) ``` ### image.load *Type:* FUNCTION Load image (PNG or JPEG) from buffer. **Parameters** - `buffer` (string) - image data buffer - `options` (table) (optional) - An optional table containing parameters for loading the image. Supported entries:
premultiply_alpha
boolean True if alpha should be premultiplied into the color components. Defaults to false.
flip_vertically
boolean True if the image contents should be flipped vertically. Defaults to false.
**Returns** - `image` (table | nil) - object or nil if loading fails. The object is a table with the following fields:
  • number width: image width
  • number height: image height
  • constant type: image type
    • image.TYPE_RGB
    • image.TYPE_RGBA
    • image.TYPE_LUMINANCE
    • image.TYPE_LUMINANCE_ALPHA
  • string buffer: the raw image data
**Examples** How to load an image from an URL and create a GUI texture from it: ``` local imgurl = "http://www.site.com/image.png" http.request(imgurl, "GET", function(self, id, response) local img = image.load(response.response) local tx = gui.new_texture("image_node", img.width, img.height, img.type, img.buffer) end) ``` ### image.load_buffer *Type:* FUNCTION Load image (PNG or JPEG) from a string buffer. **Parameters** - `buffer` (string) - image data buffer - `options` (table) (optional) - An optional table containing parameters for loading the image. Supported entries:
premultiply_alpha
boolean True if alpha should be premultiplied into the color components. Defaults to false.
flip_vertically
boolean True if the image contents should be flipped vertically. Defaults to false.
**Returns** - `image` (table | nil) - object or nil if loading fails. The object is a table with the following fields:
  • number width: image width
  • number height: image height
  • constant type: image type
    • image.TYPE_RGB
    • image.TYPE_RGBA
    • image.TYPE_LUMINANCE
    • image.TYPE_LUMINANCE_ALPHA
  • buffer buffer: the script buffer that holds the decompressed image data. See buffer.create how to use the buffer.
**Examples** Load an image from an URL as a buffer and create a texture resource from it: ``` local imgurl = "http://www.site.com/image.png" http.request(imgurl, "GET", function(self, id, response) local img = image.load_buffer(response.response, { flip_vertically = true }) local tparams = { width = img.width, height = img.height, type = graphics.TEXTURE_TYPE_2D, format = graphics.TEXTURE_FORMAT_RGBA } local my_texture_id = resource.create_texture("/my_custom_texture.texturec", tparams, img.buffer) -- Apply the texture to a model go.set("/go1#model", "texture0", my_texture_id) end) ``` ### image.TYPE_LUMINANCE *Type:* CONSTANT luminance image type ### image.TYPE_LUMINANCE_ALPHA *Type:* CONSTANT luminance image type ### image.TYPE_RGB *Type:* CONSTANT RGB image type ### image.TYPE_RGBA *Type:* CONSTANT RGBA image type # Io {#apis:io-lua} **Namespace:** `io` **Language:** Lua **Type:** Defold Lua **File:** `lua_io.doc_h` **Source:** `engine/lua/src/lua_io.doc_h` Documentation for the Lua io standard library. From [Lua 5.1 Reference Manual](https://www.lua.org/manual/5.1/) by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes. Copyright © 2006-2012 Lua.org, PUC-Rio. Freely available under the terms of the [Lua license](https://www.lua.org/license.html). ## API ### file:close *Type:* FUNCTION Closes file. Note that files are automatically closed when their handles are garbage collected, but that takes an unpredictable amount of time to happen. ### file:flush *Type:* FUNCTION Saves any written data to file. ### file:lines *Type:* FUNCTION Returns an iterator function that, each time it is called, returns a new line from the file. Therefore, the construction ``` for line in file:lines() do body end ``` will iterate over all lines of the file. (Unlike io.lines, this function does not close the file when the loop ends.) ### file:read *Type:* FUNCTION Reads the file file, according to the given formats, which specify what to read. For each format, the function returns a string (or a number) with the characters read, or nil if it cannot read data with the specified format. When called without formats, it uses a default format that reads the entire next line (see below). The available formats are "*n" reads a number; this is the only format that returns a number instead of a string. "*a" reads the whole file, starting at the current position. On end of file, it returns the empty string. "*l" reads the next line (skipping the end of line), returning nil on end of file. This is the default format. number reads a string with up to this number of characters, returning nil on end of file. If number is zero, it reads nothing and returns an empty string, or nil on end of file. **Parameters** - `...` ### file:seek *Type:* FUNCTION Sets and gets the file position, measured from the beginning of the file, to the position given by offset plus a base specified by the string whence, as follows: "set" base is position 0 (beginning of the file); "cur" base is current position; "end" base is end of file; In case of success, function seek returns the final file position, measured in bytes from the beginning of the file. If this function fails, it returns nil, plus a string describing the error. The default value for whence is "cur", and for offset is 0. Therefore, the call file:seek() returns the current file position, without changing it; the call file:seek("set") sets the position to the beginning of the file (and returns 0); and the call file:seek("end") sets the position to the end of the file, and returns its size. **Parameters** - `whence` (string) (optional) - `offset` (number) (optional) ### file:setvbuf *Type:* FUNCTION Sets the buffering mode for an output file. There are three available modes: "no" no buffering; the result of any output operation appears immediately. "full" full buffering; output operation is performed only when the buffer is full (or when you explicitly flush the file ). "line" line buffering; output is buffered until a newline is output or there is any input from some special files (such as a terminal device). For the last two cases, size specifies the size of the buffer, in bytes. The default is an appropriate size. **Parameters** - `mode` (string) - `size` (number) (optional) ### file:write *Type:* FUNCTION Writes the value of each of its arguments to the file. The arguments must be strings or numbers. To write other values, use tostring or string.format before write. **Parameters** - `...` ### io.close *Type:* FUNCTION Equivalent to file:close(). Without a file, closes the default output file. **Parameters** - `file` (file | nil) (optional) ### io.flush *Type:* FUNCTION Equivalent to file:flush over the default output file. ### io.input *Type:* FUNCTION When called with a file name, it opens the named file (in text mode), and sets its handle as the default input file. When called with a file handle, it simply sets this file handle as the default input file. When called without parameters, it returns the current default input file. In case of errors this function raises the error, instead of returning an error code. **Parameters** - `file` (string | file) (optional) ### io.lines *Type:* FUNCTION Opens the given file name in read mode and returns an iterator function that, each time it is called, returns a new line from the file. Therefore, the construction ``` for line in io.lines(filename) do body end ``` will iterate over all lines of the file. When the iterator function detects the end of file, it returns nil (to finish the loop) and automatically closes the file. The call io.lines() (with no file name) is equivalent to io.input():lines(); that is, it iterates over the lines of the default input file. In this case it does not close the file when the loop ends. **Parameters** - `filename` (string) (optional) ### io.open *Type:* FUNCTION This function opens a file, in the mode specified in the string mode. It returns a new file handle, or, in case of errors, nil plus an error message. The mode string can be any of the following: "r" read mode (the default); "w" write mode; "a" append mode; "r+" update mode, all previous data is preserved; "w+" update mode, all previous data is erased; "a+" append update mode, previous data is preserved, writing is only allowed at the end of file. The mode string can also have a 'b' at the end, which is needed in some systems to open the file in binary mode. This string is exactly what is used in the standard C function fopen. **Parameters** - `filename` (string) - `mode` (string) (optional) ### io.output *Type:* FUNCTION Similar to io.input, but operates over the default output file. **Parameters** - `file` (file) (optional) ### io.popen *Type:* FUNCTION Starts program prog in a separated process and returns a file handle that you can use to read data from this program (if mode is "r", the default) or to write data to this program (if mode is "w"). This function is system dependent and is not available on all platforms. **Parameters** - `prog` (string) - `mode` (string) (optional) ### io.read *Type:* FUNCTION Equivalent to io.input():read. **Parameters** - `...` ### io.tmpfile *Type:* FUNCTION Returns a handle for a temporary file. This file is opened in update mode and it is automatically removed when the program ends. ### io.type *Type:* FUNCTION Checks whether obj is a valid file handle. Returns the string "file" if obj is an open file handle, "closed file" if obj is a closed file handle, or nil if obj is not a file handle. **Parameters** - `obj` (file) ### io.write *Type:* FUNCTION Equivalent to io.output():write. **Parameters** - `...` # JSON {#apis:json-lua} **Namespace:** `json` **Language:** Lua **Type:** Defold Lua **File:** `script_json.cpp` **Source:** `engine/script/src/script_json.cpp` Manipulation of JSON data strings. ## API ### json.decode *Type:* FUNCTION Decode a string of JSON data into a Lua table. A Lua error is raised for syntax errors. **Parameters** - `json` (string) - json data - `options` (table) (optional) - table with decode options
  • boolean decode_null_as_userdata: wether to decode a JSON null value as json.null or nil (default is nil)
**Returns** - `data` (table) - decoded json **Examples** Converting a string containing JSON data into a Lua table: ``` function init(self) local jsonstring = '{"persons":[{"name":"John Doe"},{"name":"Darth Vader"}]}' local data = json.decode(jsonstring) pprint(data) end ``` Results in the following printout: ``` { persons = { 1 = { name = John Doe, } 2 = { name = Darth Vader, } } } ``` ### json.encode *Type:* FUNCTION Encode a lua table to a JSON string. A Lua error is raised for syntax errors. **Parameters** - `tbl` (table) - lua table to encode - `options` (table) (optional) - table with encode options
  • string encode_empty_table_as_object: wether to encode an empty table as an JSON object or array (default is object)
**Returns** - `json` (string) - encoded json **Examples** Convert a lua table to a JSON string: ``` function init(self) local tbl = { persons = { { name = "John Doe"}, { name = "Darth Vader"} } } local jsonstring = json.encode(tbl) pprint(jsonstring) end ``` Results in the following printout: ``` {"persons":[{"name":"John Doe"},{"name":"Darth Vader"}]} ``` ### json.null *Type:* VARIABLE Represents the null primitive from a json file # Label {#apis:label-lua} **Namespace:** `label` **Language:** Lua **Type:** Defold Lua **File:** `script_label.cpp` **Source:** `engine/gamesys/src/gamesys/scripts/script_label.cpp` Functions to manipulate a label component. ## API ### color *Type:* PROPERTY The color of the label. The type of the property is vector4. **Examples** ``` function init(self) -- Get the current color's y component local red_component = go.get("#label", "color.y") -- Animate the color go.animate("#label", "color", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(0,1,0,1), go.EASING_INOUTSINE, 1) end ``` ### font *Type:* PROPERTY The font used when rendering the label. The type of the property is hash. **Examples** How to set font using a script property (see resource.font) ``` go.property("my_font", resource.font("/font.font")) function init(self) go.set("#label", "font", self.my_font) end ``` ### label.get_text *Type:* FUNCTION Gets the text from a label component **Parameters** - `url` (string | hash | url) - the label to get the text from **Returns** - `metrics` (string) - the label text **Examples** ``` function init(self) local text = label.get_text("#label") print(text) end ``` ### label.set_text *Type:* FUNCTION Sets the text of a label component This method uses the message passing that means the value will be set after dispatch messages step. More information is available in the Application Lifecycle manual. **Parameters** - `url` (string | hash | url) - the label that should have a constant set - `text` (string | number) - the text **Examples** ``` function init(self) label.set_text("#label", "Hello World!") end ``` ### leading *Type:* PROPERTY The leading of the label. This value is used to scale the line spacing of text. The type of the property is number. **Examples** How to query a label's leading: ``` function init(self) -- get leading from component "label" local leading = go.get("#label", "leading") -- do something useful leading = leading * 1.2 go.set("#label", "leading", leading) end ``` ### line_break *Type:* PROPERTY The line break of the label. This value is used to adjust the vertical spacing of characters in the text. The type of the property is boolean. **Examples** How to query a label's line break: ``` function init(self) -- get line_break from component "label" local line_break = go.get("#label", "line_break") -- do something useful go.set("#label", "line_break", false) end ``` ### material *Type:* PROPERTY The material used when rendering the label. The type of the property is hash. **Examples** How to set material using a script property (see resource.material) ``` go.property("my_material", resource.material("/material.material")) function init(self) go.set("#label", "material", self.my_material) end ``` ### outline *Type:* PROPERTY The outline color of the label. The type of the property is vector4. **Examples** ``` function init(self) -- Get the current outline color local outline = go.get("#label", "outline") -- Animate the property go.animate("#label", "outline", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(0,1,0,1), go.EASING_INOUTSINE, 1) end ``` ### scale *Type:* PROPERTY The scale of the label. The type of the property is number (uniform) or vector3 (non uniform). **Examples** How to scale a label independently along the X and Y axis: ``` function init(self) -- Double the y-axis scaling on component "label" local yscale = go.get("#label", "scale.y") go.set("#label", "scale.y", yscale * 2) -- Set the new scale altogether go.set("#label", "scale", vmath.vector3(2,2,2)) -- Animate the scale go.animate("#label", "scale", go.PLAYBACK_LOOP_PINGPONG, vmath.vector3(2,2,2), go.EASING_INOUTSINE, 1) end ``` ### shadow *Type:* PROPERTY The shadow color of the label. The type of the property is vector4. **Examples** ``` function init(self) -- Get the current shadow color local shadow = go.get("#label", "shadow") -- Animate the property go.animate("#label", "shadow", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(0,1,0,1), go.EASING_INOUTSINE, 1) end ``` ### size *Type:* PROPERTY Returns the size of the label. The size will constrain the text if line break is enabled. The type of the property is vector3. **Examples** How to query a label's size, either as a vector or selecting a specific dimension: ``` function init(self) -- get size from component "label" local size = go.get("#label", "size") local sizex = go.get("#label", "size.x") -- do something useful assert(size.x == sizex) end ``` ### tracking *Type:* PROPERTY The tracking of the label. This value is used to adjust the vertical spacing of characters in the text. The type of the property is number. **Examples** How to query a label's tracking: ``` function init(self) -- get tracking from component "label" local tracking = go.get("#label", "tracking") -- do something useful tracking = tracking * 1.2 go.set("#label", "tracking", tracking) end ``` # LiveUpdate {#apis:liveupdate-lua} **Namespace:** `liveupdate` **Language:** Lua **Type:** Defold Lua **File:** `script_liveupdate.h` **Source:** `engine/liveupdate/src/script_liveupdate.h` Functions and constants to access resources. ## API ### liveupdate.add_mount *Type:* FUNCTION Adds a resource mount to the resource system. The mounts are persisted between sessions. After the mount succeeded, the resources are available to load. (i.e. no reboot required) **Notes** - The request is asynchronous - Names cannot start with '_' - Priority must be >= 0 **Parameters** - `name` (string) - Unique name of the mount - `uri` (string) - The uri of the mount, including the scheme. Currently supported schemes are 'zip' and 'archive'. - `priority` (number) - Priority of mount. Larger priority takes prescedence - `callback` (function) - Callback after the asynchronous request completed **Returns** - `result` (number) - The result of the request **Examples** Add multiple mounts. Higher priority takes precedence. ``` liveupdate.add_mount("common", "zip:/path/to/common_stuff.zip", 10, function (result) end) -- base pack liveupdate.add_mount("levelpack_1", "zip:/path/to/levels_1_to_20.zip", 20, function (result) end) -- level pack liveupdate.add_mount("season_pack_1", "zip:/path/to/easter_pack_1.zip", 30, function (result) end) -- season pack, overriding content in the other packs ``` ### liveupdate.get_mounts *Type:* FUNCTION Get an array of the current mounts This can be used to determine if a new mount is needed or not **Returns** - `mounts` (table) - Array of mounts **Examples** Output the current resource mounts ``` pprint("MOUNTS", liveupdate.get_mounts()) ``` Give an output like: ``` DEBUG:SCRIPT: MOUNTS, { --[[0x119667bf0]] 1 = { --[[0x119667c50]] name = "liveupdate", uri = "zip:/device/path/to/acchives/liveupdate.zip", priority = 5 }, 2 = { --[[0x119667d50]] name = "_base", uri = "archive:build/default/game.dmanifest", priority = -10 } } ``` ### liveupdate.LIVEUPDATE_BUNDLED_RESOURCE_MISMATCH *Type:* CONSTANT Mismatch between between expected bundled resources and actual bundled resources. The manifest expects a resource to be in the bundle, but it was not found in the bundle. This is typically the case when a non-excluded resource was modified between publishing the bundle and publishing the manifest. ### liveupdate.LIVEUPDATE_ENGINE_VERSION_MISMATCH *Type:* CONSTANT Mismatch between running engine version and engine versions supported by manifest. ### liveupdate.LIVEUPDATE_FORMAT_ERROR *Type:* CONSTANT Failed to parse manifest data buffer. The manifest was probably produced by a different engine version. ### liveupdate.LIVEUPDATE_INVAL *Type:* CONSTANT Argument was invalid ### liveupdate.LIVEUPDATE_INVALID_HEADER *Type:* CONSTANT The handled resource is invalid. ### liveupdate.LIVEUPDATE_INVALID_RESOURCE *Type:* CONSTANT The header of the resource is invalid. ### liveupdate.LIVEUPDATE_IO_ERROR *Type:* CONSTANT I/O operation failed ### liveupdate.LIVEUPDATE_MEM_ERROR *Type:* CONSTANT Memory wasn't allocated ### liveupdate.LIVEUPDATE_OK *Type:* CONSTANT LIVEUPDATE_OK ### liveupdate.LIVEUPDATE_SCHEME_MISMATCH *Type:* CONSTANT Mismatch between scheme used to load resources. Resources are loaded with a different scheme than from manifest, for example over HTTP or directly from file. This is typically the case when running the game directly from the editor instead of from a bundle. ### liveupdate.LIVEUPDATE_SIGNATURE_MISMATCH *Type:* CONSTANT Mismatch between expected and actual integrity data for legacy liveupdate verification. ### liveupdate.LIVEUPDATE_UNKNOWN *Type:* CONSTANT Unspecified error ### liveupdate.LIVEUPDATE_VERSION_MISMATCH *Type:* CONSTANT Mismatch between manifest expected version and actual version. ### liveupdate.remove_mount *Type:* FUNCTION Remove a mount the resource system. The remaining mounts are persisted between sessions. Removing a mount does not affect any loaded resources. **Notes** - The call is synchronous **Parameters** - `name` (string) - Unique name of the mount **Returns** - `result` (number) - The result of the call **Examples** Add multiple mounts. Higher priority takes precedence. ``` liveupdate.remove_mount("season_pack_1") ``` # Math {#apis:math-lua} **Namespace:** `math` **Language:** Lua **Type:** Defold Lua **File:** `lua_math.doc_h` **Source:** `engine/lua/src/lua_math.doc_h` Documentation for the Lua math standard library. From [Lua 5.1 Reference Manual](https://www.lua.org/manual/5.1/) by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes. Copyright © 2006-2012 Lua.org, PUC-Rio. Freely available under the terms of the [Lua license](https://www.lua.org/license.html). ## API ### math.abs *Type:* FUNCTION Returns the absolute value of x. **Parameters** - `x` (number) ### math.acos *Type:* FUNCTION Returns the arc cosine of x (in radians). **Parameters** - `x` (number) ### math.asin *Type:* FUNCTION Returns the arc sine of x (in radians). **Parameters** - `x` (number) ### math.atan *Type:* FUNCTION Returns the arc tangent of x (in radians). **Parameters** - `x` (number) ### math.atan2 *Type:* FUNCTION Returns the arc tangent of y/x (in radians), but uses the signs of both parameters to find the quadrant of the result. (It also handles correctly the case of x being zero.) **Parameters** - `y` (number) - `x` (number) ### math.ceil *Type:* FUNCTION Returns the smallest integer larger than or equal to x. **Parameters** - `x` (number) ### math.cos *Type:* FUNCTION Returns the cosine of x (assumed to be in radians). **Parameters** - `x` (number) ### math.cosh *Type:* FUNCTION Returns the hyperbolic cosine of x. **Parameters** - `x` (number) ### math.deg *Type:* FUNCTION Returns the angle x (given in radians) in degrees. **Parameters** - `x` (number) ### math.exp *Type:* FUNCTION Returns the value ex. **Parameters** - `x` (number) ### math.floor *Type:* FUNCTION Returns the largest integer smaller than or equal to x. **Parameters** - `x` (number) ### math.fmod *Type:* FUNCTION Returns the remainder of the division of x by y that rounds the quotient towards zero. **Parameters** - `x` (number) - `y` (number) ### math.frexp *Type:* FUNCTION Returns m and e such that x = m2e, e is an integer and the absolute value of m is in the range [0.5, 1) (or zero when x is zero). **Parameters** - `x` (number) ### math.huge *Type:* VARIABLE The value HUGE_VAL, a value larger than or equal to any other numerical value. ### math.ldexp *Type:* FUNCTION Returns m2e (e should be an integer). **Parameters** - `m` (number) - `e` (number) ### math.log *Type:* FUNCTION Returns the natural logarithm of x. **Parameters** - `x` (number) ### math.log10 *Type:* FUNCTION Returns the base-10 logarithm of x. **Parameters** - `x` (number) ### math.max *Type:* FUNCTION Returns the maximum value among its arguments. **Parameters** - `x` (number) - `...` ### math.min *Type:* FUNCTION Returns the minimum value among its arguments. **Parameters** - `x` (number) - `...` ### math.modf *Type:* FUNCTION Returns two numbers, the integral part of x and the fractional part of x. **Parameters** - `x` (number) ### math.pi *Type:* VARIABLE The value of PI. ### math.pow *Type:* FUNCTION Returns xy. (You can also use the expression x^y to compute this value.) **Parameters** - `x` (number) - `y` (number) ### math.rad *Type:* FUNCTION Returns the angle x (given in degrees) in radians. **Parameters** - `x` (number) ### math.random *Type:* FUNCTION This function is an interface to the simple pseudo-random generator function rand provided by ANSI C. (No guarantees can be given for its statistical properties.) When called without arguments, returns a uniform pseudo-random real number in the range [0,1). When called with an integer number m, math.random returns a uniform pseudo-random integer in the range [1, m]. When called with two integer numbers m and n, math.random returns a uniform pseudo-random integer in the range [m, n]. **Parameters** - `m` (number) (optional) - `n` (number) (optional) ### math.randomseed *Type:* FUNCTION Sets x as the "seed" for the pseudo-random generator: equal seeds produce equal sequences of numbers. **Parameters** - `x` (number) ### math.sin *Type:* FUNCTION Returns the sine of x (assumed to be in radians). **Parameters** - `x` (number) ### math.sinh *Type:* FUNCTION Returns the hyperbolic sine of x. **Parameters** - `x` (number) ### math.sqrt *Type:* FUNCTION Returns the square root of x. (You can also use the expression x^0.5 to compute this value.) **Parameters** - `x` (number) ### math.tan *Type:* FUNCTION Returns the tangent of x (assumed to be in radians). **Parameters** - `x` (number) ### math.tanh *Type:* FUNCTION Returns the hyperbolic tangent of x. **Parameters** - `x` (number) # Model {#apis:model-lua} **Namespace:** `model` **Language:** Lua **Type:** Defold Lua **File:** `model_ddf.proto` **Source:** `engine/gamesys/proto/gamesys/model_ddf.proto` Model API documentation ## API ### animation *Type:* PROPERTY The current animation set on the component. The type of the property is hash. **Examples** How to read the current animation from a model component: ``` function init(self) -- Get the current animation on component "model" local animation = go.get("#model", "animation") if animation == hash("run_left") then -- Running left. Do something... end end ``` ### cursor *Type:* PROPERTY The normalized animation cursor. The type of the property is number. Please note that model events may not fire as expected when the cursor is manipulated directly. **Examples** How to get the normalized cursor value: ``` function init(self) -- Get the cursor value on component "model" cursor = go.get("#model", "cursor") end ``` How to animate the cursor from 0.0 to 1.0 using linear easing for 2.0 seconds: ``` function init(self) -- Get the current value on component "model" go.set("#model", "cursor", 0.0) -- Animate the cursor value go.animate("#model", "cursor", go.PLAYBACK_LOOP_FORWARD, 1.0, go.EASING_LINEAR, 2) end ``` ### material *Type:* PROPERTY The material used when rendering the model. The type of the property is hash. **Examples** How to set material using a script property (see resource.material): ``` go.property("my_material", resource.material("/material.material")) function init(self) go.set("#model", "material", self.my_material) end ``` ### model.cancel *Type:* FUNCTION Cancels all animation on a model component. **Parameters** - `url` (string | hash | url) - the model for which to cancel the animation ### model.get_aabb *Type:* FUNCTION Get AABB of the whole model in local coordinate space. AABB information return as a table with min and max fields, where min and max has type vmath.vector3. **Parameters** - `url` (string | hash | url) - the model **Returns** - `aabb` (table) - A table containing AABB of the model. If model has no meshes - return vmath.vector3(0,0,0) for min and max fields. **Examples** ``` model.get_aabb("#model") -> { min = vmath.vector3(-2.5, -3.0, 0), max = vmath.vector3(1.5, 5.5, 0) } model.get_aabb("#empty") -> { min = vmath.vector3(0, 0, 0), max = vmath.vector3(0, 0, 0) } ``` ### model.get_go *Type:* FUNCTION Gets the id of the game object that corresponds to a model skeleton bone. The returned game object can be used for parenting and transform queries. This function has complexity O(n), where n is the number of bones in the model skeleton. Game objects corresponding to a model skeleton bone can not be individually deleted. **Parameters** - `url` (string | hash | url) - the model to query - `bone_id` (string | hash) - id of the corresponding bone **Returns** - `id` (hash) - id of the game object **Examples** The following examples assumes that the model component has id "model". How to parent the game object of the calling script to the "right_hand" bone of the model in a player game object: ``` function init(self) local parent = model.get_go("player#model", "right_hand") msg.post(".", "set_parent", {parent_id = parent}) end ``` ### model.get_mesh_aabb *Type:* FUNCTION Get AABB of all meshes. AABB information return as a table with min and max fields, where min and max has type vmath.vector3. **Parameters** - `url` (string | hash | url) - the model **Returns** - `aabb` (table) - A table containing info about all AABB in the format **Examples** ``` model.get_mesh_aabb("#model") -> { hash("Sword") = { min = vmath.vector3(-0.5, -0.5, 0), max = vmath.vector3(0.5, 0.5, 0) }, hash("Shield") = { min = vmath.vector3(-0.5, -0.5, -0.5), max = vmath.vector3(0.5, 0.5, 0.5) } } ``` ### model.get_mesh_enabled *Type:* FUNCTION Get the enabled state of a mesh **Parameters** - `url` (string | hash | url) - the model - `mesh_id` (string | hash | url) - the id of the mesh **Returns** - `enabled` (boolean) - true if the mesh is visible, false otherwise **Examples** ``` function init(self) if model.get_mesh_enabled("#model", "Sword") then -- set properties specific for the sword self.weapon_properties = game.data.weapons["Sword"] end end ``` ### model.play_anim *Type:* FUNCTION Plays an animation on a model component with specified playback mode and parameters. An optional completion callback function can be provided that will be called when the animation has completed playing. If no function is provided, a model_animation_done message is sent to the script that started the animation. The callback is not called (or message sent) if the animation is cancelled with model.cancel. The callback is called (or message sent) only for animations that play with the following playback modes: go.PLAYBACK_ONCE_FORWARD go.PLAYBACK_ONCE_BACKWARD go.PLAYBACK_ONCE_PINGPONG **Parameters** - `url` (string | hash | url) - the model for which to play the animation - `anim_id` (string | hash) - id of the animation to play - `playback` (constant) - playback mode of the animation
  • go.PLAYBACK_ONCE_FORWARD
  • go.PLAYBACK_ONCE_BACKWARD
  • go.PLAYBACK_ONCE_PINGPONG
  • go.PLAYBACK_LOOP_FORWARD
  • go.PLAYBACK_LOOP_BACKWARD
  • go.PLAYBACK_LOOP_PINGPONG
- `play_properties` (table) (optional) - optional table with properties Play properties table:
blend_duration
number Duration of a linear blend between the current and new animation.
offset
number The normalized initial value of the animation cursor when the animation starts playing.
playback_rate
number The rate with which the animation will be played. Must be positive.
- `complete_function` (function(self, message_id, message, sender)) (optional) - function to call when the animation has completed.
self
object The current object.
message_id
hash The name of the completion message, "model_animation_done".
message
table Information about the completion:
  • hash animation_id - the animation that was completed.
  • constant playback - the playback mode for the animation.
sender
url The invoker of the callback: the model component.
**Examples** The following examples assumes that the model has id "model". How to play the "jump" animation followed by the "run" animation: ``` local function anim_done(self, message_id, message, sender) if message_id == hash("model_animation_done") then if message.animation_id == hash("jump") then -- open animation done, chain with "run" local properties = { blend_duration = 0.2 } model.play_anim(url, "run", go.PLAYBACK_LOOP_FORWARD, properties, anim_done) end end end function init(self) local url = msg.url("#model") local play_properties = { blend_duration = 0.1 } -- first blend during 0.1 sec into the jump, then during 0.2 s into the run animation model.play_anim(url, "jump", go.PLAYBACK_ONCE_FORWARD, play_properties, anim_done) end ``` ### model.set_mesh_enabled *Type:* FUNCTION Enable or disable visibility of a mesh **Parameters** - `url` (string | hash | url) - the model - `mesh_id` (string | hash | url) - the id of the mesh - `enabled` (boolean) - true if the mesh should be visible, false if it should be hideen **Examples** ``` function init(self) model.set_mesh_enabled("#model", "Sword", false) -- hide the sword model.set_mesh_enabled("#model", "Axe", true) -- show the axe end ``` ### model_animation_done *Type:* MESSAGE This message is sent when a Model animation has finished playing back to the script that started the animation. No message is sent if a completion callback function was supplied when the animation was started. No message is sent if the animation is cancelled with model.cancel(). This message is sent only for animations that play with the following playback modes: go.PLAYBACK_ONCE_FORWARD go.PLAYBACK_ONCE_BACKWARD go.PLAYBACK_ONCE_PINGPONG **Parameters** - `animation_id` (hash) - the id of the completed animation - `playback` (constant) - the playback mode of the completed animation **Examples** ``` function on_message(self, message_id, message, sender) if message_id == hash("model_animation_done") then if message.animation_id == hash("run") and message.playback == go.PLAYBACK_ONCE_FORWARD then -- The animation "run" has finished running forward. end end end ``` ### playback_rate *Type:* PROPERTY The animation playback rate. A multiplier to the animation playback rate. The type of the property is number. **Examples** How to set the playback_rate on component "model" to play at double the current speed: ``` function init(self) -- Get the current value on component "model" playback_rate = go.get("#model", "playback_rate") -- Set the playback_rate to double the previous value. go.set("#model", "playback_rate", playback_rate * 2) end ``` The playback_rate is a non-negative number, a negative value will be clamped to 0. ### textureN *Type:* PROPERTY The texture hash id of the model. Used for getting/setting model texture for unit 0-7 **Examples** How to set texture using a script property (see resource.texture): ``` go.property("my_texture", texture("/texture.png")) function init(self) go.set("#model", "texture0", self.my_texture) end ``` See resource.set_texture for an example on how to set the texture of an atlas. # Message {#apis:msg-lua} **Namespace:** `msg` **Language:** Lua **Type:** Defold Lua **File:** `script_msg.cpp` **Source:** `engine/script/src/script_msg.cpp` Functions for passing messages and constructing URL objects. ## API ### msg.post *Type:* FUNCTION Post a message to a receiving URL. The most common case is to send messages to a component. If the component part of the receiver is omitted, the message is broadcast to all components in the game object. The following receiver shorthands are available: "." the current game object "#" the current component There is a 2 kilobyte limit to the message parameter table size. **Parameters** - `receiver` (string | url | hash) - The receiver must be a string in URL-format, a URL object or a hashed string. - `message_id` (string | hash) - The id must be a string or a hashed string. - `message` (table | nil) (optional) - a lua table with message parameters to send. **Examples** Send "enable" to the sprite "my_sprite" in "my_gameobject": ``` msg.post("my_gameobject#my_sprite", "enable") ``` Send a "my_message" to an url with some additional data: ``` local params = {my_parameter = "my_value"} msg.post(my_url, "my_message", params) ``` ### msg.url *Type:* FUNCTION This is equivalent to msg.url(nil) or msg.url("#"), which creates an url to the current script component. **Returns** - `url` (url) - a new URL **Examples** Create a new URL which will address the current script: ``` local my_url = msg.url() print(my_url) --> url: [current_collection:/my_instance#my_component] ``` ### msg.url *Type:* FUNCTION The format of the string must be [socket:][path][#fragment], which is similar to a HTTP URL. When addressing instances: socket is the name of a valid world (a collection) path is the id of the instance, which can either be relative the instance of the calling script or global fragment would be the id of the desired component In addition, the following shorthands are available: "." the current game object "#" the current component **Parameters** - `urlstring` (string) - string to create the url from **Returns** - `url` (url) - a new URL **Examples** ``` local my_url = msg.url("#my_component") print(my_url) --> url: [current_collection:/my_instance#my_component] local my_url = msg.url("my_collection:/my_sub_collection/my_instance#my_component") print(my_url) --> url: [my_collection:/my_sub_collection/my_instance#my_component] local my_url = msg.url("my_socket:") print(my_url) --> url: [my_collection:] ``` ### msg.url *Type:* FUNCTION creates a new URL from separate arguments **Parameters** - `socket` (string | hash) (optional) - socket of the URL - `path` (string | hash) (optional) - path of the URL - `fragment` (string | hash) (optional) - fragment of the URL **Returns** - `url` (url) - a new URL **Examples** ``` local my_socket = "main" -- specify by valid name local my_path = hash("/my_collection/my_gameobject") -- specify as string or hash local my_fragment = "component" -- specify as string or hash local my_url = msg.url(my_socket, my_path, my_fragment) print(my_url) --> url: [main:/my_collection/my_gameobject#component] print(my_url.socket) --> 786443 (internal numeric value) print(my_url.path) --> hash: [/my_collection/my_gameobject] print(my_url.fragment) --> hash: [component] ``` # Os {#apis:os-lua} **Namespace:** `os` **Language:** Lua **Type:** Defold Lua **File:** `lua_os.doc_h` **Source:** `engine/lua/src/lua_os.doc_h` Documentation for the Lua os standard library. From [Lua 5.1 Reference Manual](https://www.lua.org/manual/5.1/) by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes. Copyright © 2006-2012 Lua.org, PUC-Rio. Freely available under the terms of the [Lua license](https://www.lua.org/license.html). ## API ### os.clock *Type:* FUNCTION Returns an approximation of the amount in seconds of CPU time used by the program. ### os.date *Type:* FUNCTION Returns a string or a table containing date and time, formatted according to the given string format. If the time argument is present, this is the time to be formatted (see the os.time function for a description of this value). Otherwise, date formats the current time. If format starts with '!', then the date is formatted in Coordinated Universal Time. After this optional character, if format is the string "*t", then date returns a table with the following fields: year (four digits), month (1--12), day (1--31), hour (0--23), min (0--59), sec (0--61), wday (weekday, Sunday is 1), yday (day of the year), and isdst (daylight saving flag, a boolean). If format is not "*t", then date returns the date as a string, formatted according to the same rules as the C function strftime. When called without arguments, date returns a reasonable date and time representation that depends on the host system and on the current locale (that is, os.date() is equivalent to os.date("%c")). **Parameters** - `format` (string) (optional) - `time` (number) (optional) ### os.difftime *Type:* FUNCTION Returns the number of seconds from time t1 to time t2. In POSIX, Windows, and some other systems, this value is exactly t2-t1. **Parameters** - `t2` (number) - `t1` (number) ### os.execute *Type:* FUNCTION This function is equivalent to the C function system. It passes command to be executed by an operating system shell. It returns a status code, which is system-dependent. If command is absent, then it returns nonzero if a shell is available and zero otherwise. **Parameters** - `command` (string) (optional) ### os.exit *Type:* FUNCTION Calls the C function exit, with an optional code, to terminate the host program. The default value for code is the success code. Calling os.exit will do a hard exit which will not run the engine shutdown code. This may cause crashes on exit. The recommended way to terminate your game is by using the exit message which does a graceful shutdown. msg.post("@system:", "exit", {code = 0}) **Parameters** - `code` (number) (optional) ### os.getenv *Type:* FUNCTION Returns the value of the process environment variable varname, or nil if the variable is not defined. **Parameters** - `varname` (string) ### os.remove *Type:* FUNCTION Deletes the file or directory with the given name. Directories must be empty to be removed. If this function fails, it returns nil, plus a string describing the error. **Parameters** - `filename` (string) ### os.rename *Type:* FUNCTION Renames file or directory named oldname to newname. If this function fails, it returns nil, plus a string describing the error. **Parameters** - `oldname` (string) - `newname` (string) ### os.setlocale *Type:* FUNCTION Sets the current locale of the program. locale is a string specifying a locale; category is an optional string describing which category to change: "all", "collate", "ctype", "monetary", "numeric", or "time"; the default category is "all". The function returns the name of the new locale, or nil if the request cannot be honored. If locale is the empty string, the current locale is set to an implementation-defined native locale. If locale is the string "C", the current locale is set to the standard C locale. When called with nil as the first argument, this function only returns the name of the current locale for the given category. **Parameters** - `locale` (string) - `category` (string) (optional) ### os.time *Type:* FUNCTION Returns the current time when called without arguments, or a time representing the date and time specified by the given table. This table must have fields year, month, and day, and may have fields hour, min, sec, and isdst (for a description of these fields, see the os.date function). The returned value is a number, whose meaning depends on your system. In POSIX, Windows, and some other systems, this number counts the number of seconds since some given start time (the "epoch"). In other systems, the meaning is not specified, and the number returned by time can be used only as an argument to date and difftime. **Parameters** - `table` (table) (optional) ### os.tmpname *Type:* FUNCTION Returns a string with a file name that can be used for a temporary file. The file must be explicitly opened before its use and explicitly removed when no longer needed. On some systems (POSIX), this function also creates a file with that name, to avoid security risks. (Someone else might create the file with wrong permissions in the time between getting the name and creating the file.) You still have to open the file to use it and to remove it (even if you do not use it). When possible, you may prefer to use io.tmpfile, which automatically removes the file when the program ends. # Package {#apis:package-lua} **Namespace:** `package` **Language:** Lua **Type:** Defold Lua **File:** `lua_package.doc_h` **Source:** `engine/lua/src/lua_package.doc_h` Documentation for the Lua package standard library. From [Lua 5.1 Reference Manual](https://www.lua.org/manual/5.1/) by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes. Copyright © 2006-2012 Lua.org, PUC-Rio. Freely available under the terms of the [Lua license](https://www.lua.org/license.html). ## API ### package.cpath *Type:* FUNCTION The path used by require to search for a C loader. Lua initializes the C path package.cpath in the same way it initializes the Lua path package.path, using the environment variable LUA_CPATH or a default path defined in luaconf.h. ### package.loaded *Type:* FUNCTION A table used by require to control which modules are already loaded. When you require a module modname and package.loaded[modname] is not false, require simply returns the value stored there. ### package.loaders *Type:* FUNCTION A table used by require to control how to load modules. Each entry in this table is a searcher function. When looking for a module, require calls each of these searchers in ascending order, with the module name (the argument given to require) as its sole parameter. The function can return another function (the module loader) or a string explaining why it did not find that module (or nil if it has nothing to say). Lua initializes this table with four functions. The first searcher simply looks for a loader in the package.preload table. The second searcher looks for a loader as a Lua library, using the path stored at package.path. A path is a sequence of templates separated by semicolons. For each template, the searcher will change each interrogation mark in the template by filename, which is the module name with each dot replaced by a "directory separator" (such as "/" in Unix); then it will try to open the resulting file name. So, for instance, if the Lua path is the string ``` "./?.lua;./?.lc;/usr/local/?/init.lua" ``` the search for a Lua file for module foo will try to open the files ./foo.lua, ./foo.lc, and /usr/local/foo/init.lua, in that order. The third searcher looks for a loader as a C library, using the path given by the variable package.cpath. For instance, if the C path is the string ``` "./?.so;./?.dll;/usr/local/?/init.so" ``` the searcher for module foo will try to open the files ./foo.so, ./foo.dll, and /usr/local/foo/init.so, in that order. Once it finds a C library, this searcher first uses a dynamic link facility to link the application with the library. Then it tries to find a C function inside the library to be used as the loader. The name of this C function is the string "luaopen_" concatenated with a copy of the module name where each dot is replaced by an underscore. Moreover, if the module name has a hyphen, its prefix up to (and including) the first hyphen is removed. For instance, if the module name is a.v1-b.c, the function name will be luaopen_b_c. The fourth searcher tries an all-in-one loader. It searches the C path for a library for the root name of the given module. For instance, when requiring a.b.c, it will search for a C library for a. If found, it looks into it for an open function for the submodule; in our example, that would be luaopen_a_b_c. With this facility, a package can pack several C submodules into one single library, with each submodule keeping its original open function. ### package.loadlib *Type:* FUNCTION Dynamically links the host program with the C library libname. Inside this library, looks for a function funcname and returns this function as a C function. (So, funcname must follow the protocol ). This is a low-level function. It completely bypasses the package and module system. Unlike require, it does not perform any path searching and does not automatically adds extensions. libname must be the complete file name of the C library, including if necessary a path and extension. funcname must be the exact name exported by the C library (which may depend on the C compiler and linker used). This function is not supported by ANSI C. As such, it is only available on some platforms (Windows, Linux, Mac OS X, Solaris, BSD, plus other Unix systems that support the dlfcn standard). **Parameters** - `libname` (string) - `funcname` (string) ### package.path *Type:* FUNCTION The path used by require to search for a Lua loader. At start-up, Lua initializes this variable with the value of the environment variable LUA_PATH or with a default path defined in luaconf.h, if the environment variable is not defined. Any ";;" in the value of the environment variable is replaced by the default path. ### package.preload *Type:* FUNCTION A table to store loaders for specific modules . ### package.seeall *Type:* FUNCTION Sets a metatable for module with its __index field referring to the global environment, so that this module inherits values from the global environment. To be used as an option to function module. **Parameters** - `module` (table) # Particle effects {#apis:particlefx-lua} **Namespace:** `particlefx` **Language:** Lua **Type:** Defold Lua **File:** `script_particlefx.cpp` **Source:** `engine/gamesys/src/gamesys/scripts/script_particlefx.cpp` Functions and properties for controlling particle effect component playback and shader constants. ## API ### animation *Type:* PROPERTY The animation used during rendering by an emitter in a particle FX component. The property type is a hash and refers to a valid animation in an atlas or a tile source resource. If the animation isn't found, and error will be thrown. **Examples** How to set and get the animation of an emitter in a particle FX. ``` local current_animation = go.get("#particlefx", "animation", { keys = { "explosion" } }) go.set("#particlefx", "animation", hash("explode_large"), { keys = { "explosion" } }) ``` ### image *Type:* PROPERTY The image used during rendering by an emitter in a particle FX component. The property type is a hash and refers to an image resource (atlas or tile source). Note: When setting the image, if the currently playing animation of the emitter isn't found in the new image, the animation will be set to the first animation found. **Examples** How to set and get the image of an emitter in a particle FX. ``` go.property("my_atlas", resource.atlas()) function init(self) go.set("#particlefx", "image", self.my_atlas, { keys = { "explosion" } }) local emitter_img = go.get("#particlefx", "image", { keys = { "explosion" } }) assert(emitter_img == self.my_atlas) end ``` ### material *Type:* PROPERTY The material used during rendering by an emitter in a particle FX component. The property type is a hash and refers to a material resource. **Examples** How to set and get the material of an emitter in a particle FX. ``` go.property("my_material", resource.material()) function init(self) go.set("#particlefx", "material", self.my_material, { keys = { "explosion" } }) local emitter_mat = go.get("#particlefx", "material", { keys = { "explosion" } }) assert(emitter_mat == self.my_material) end ``` ### particlefx.EMITTER_STATE_POSTSPAWN *Type:* CONSTANT The emitter is not spawning any particles, but has particles that are still alive. ### particlefx.EMITTER_STATE_PRESPAWN *Type:* CONSTANT The emitter will be in this state when it has been started but before spawning any particles. Normally the emitter is in this state for a short time, depending on if a start delay has been set for this emitter or not. ### particlefx.EMITTER_STATE_SLEEPING *Type:* CONSTANT The emitter does not have any living particles and will not spawn any particles in this state. ### particlefx.EMITTER_STATE_SPAWNING *Type:* CONSTANT The emitter is spawning particles. ### particlefx.play *Type:* FUNCTION Starts playing a particle FX component. Particle FX started this way need to be manually stopped through particlefx.stop(). Which particle FX to play is identified by the URL. A particle FX will continue to emit particles even if the game object the particle FX component belonged to is deleted. You can call particlefx.stop() to stop it from emitting more particles. **Parameters** - `url` (string | hash | url) - the particle fx that should start playing. - `emitter_state_function` (function(self, id, emitter, state)) (optional) - optional callback function that will be called when an emitter attached to this particlefx changes state.
self
object The current object
id
hash The id of the particle fx component
emitter
hash The id of the emitter
state
constant the new state of the emitter:
  • particlefx.EMITTER_STATE_SLEEPING
  • particlefx.EMITTER_STATE_PRESPAWN
  • particlefx.EMITTER_STATE_SPAWNING
  • particlefx.EMITTER_STATE_POSTSPAWN
**Examples** How to play a particle fx when a game object is created. The callback receives the hash of the path to the particlefx, the hash of the id of the emitter, and the new state of the emitter as particlefx.EMITTER_STATE_. ``` local function emitter_state_change(self, id, emitter, state) if emitter == hash("exhaust") and state == particlefx.EMITTER_STATE_POSTSPAWN then -- exhaust is done spawning particles... end end function init(self) particlefx.play("#particlefx", emitter_state_change) end ``` ### particlefx.reset_constant *Type:* FUNCTION Resets a shader constant for a particle FX component emitter. The constant must be defined in the material assigned to the emitter. Resetting a constant through this function implies that the value defined in the material will be used. Which particle FX to reset a constant for is identified by the URL. **Parameters** - `url` (string | hash | url) - the particle FX that should have a constant reset - `emitter` (string | hash) - the id of the emitter - `constant` (string | hash) - the name of the constant **Examples** The following examples assumes that the particle FX has id "particlefx", it contains an emitter with the id "emitter" and that the default-material in builtins is used, which defines the constant "tint". If you assign a custom material to the sprite, you can reset the constants defined there in the same manner. How to reset the tinting of particles from an emitter: ``` function init(self) particlefx.reset_constant("#particlefx", "emitter", "tint") end ``` ### particlefx.set_constant *Type:* FUNCTION Sets a shader constant for a particle FX component emitter. The constant must be defined in the material assigned to the emitter. Setting a constant through this function will override the value set for that constant in the material. The value will be overridden until particlefx.reset_constant is called. Which particle FX to set a constant for is identified by the URL. **Parameters** - `url` (string | hash | url) - the particle FX that should have a constant set - `emitter` (string | hash) - the id of the emitter - `constant` (string | hash) - the name of the constant - `value` (vector4) - the value of the constant **Examples** The following examples assumes that the particle FX has id "particlefx", it contains an emitter with the id "emitter" and that the default-material in builtins is used, which defines the constant "tint". If you assign a custom material to the sprite, you can reset the constants defined there in the same manner. How to tint particles from an emitter red: ``` function init(self) particlefx.set_constant("#particlefx", "emitter", "tint", vmath.vector4(1, 0, 0, 1)) end ``` ### particlefx.stop *Type:* FUNCTION Stops a particle FX component from playing. Stopping a particle FX does not remove already spawned particles. Which particle FX to stop is identified by the URL. **Parameters** - `url` (string | hash | url) - the particle fx that should stop playing - `options` (table) (optional) - Options when stopping the particle fx. Supported options:
  • boolean clear: instantly clear spawned particles
**Examples** How to stop a particle fx when a game object is deleted and immediately also clear any spawned particles: ``` function final(self) particlefx.stop("#particlefx", { clear = true }) end ``` # Collision object {#apis:physics-lua} **Namespace:** `physics` **Language:** Lua **Type:** Defold Lua **File:** `physics_ddf.proto` **Source:** `engine/gamesys/proto/gamesys/physics_ddf.proto` Collision object physics API documentation ## API ### angular_damping *Type:* PROPERTY The angular damping value for the collision object. Setting this value alters the damping of angular motion of the object (rotation). Valid values are between 0 (no damping) and 1 (full damping). **Examples** How to decrease a collision object component's angular damping: ``` -- get angular damping from collision object "collisionobject" in gameobject "floater" local target = "floater#collisionobject" local damping = go.get(target, "angular_damping") -- decrease it by 10% go.set(target, "angular_damping", damping * 0.9) ``` ### angular_velocity *Type:* PROPERTY The current angular velocity of the collision object component as a vector3. The velocity is measured as a rotation around the vector with a speed equivalent to the vector length in radians/s. **Replaces:** request_velocity and velocity_response **Examples** How to query and modify a collision object component's angular velocity: ``` -- get angular velocity from collision object "collisionobject" in gameobject "boulder" local velocity = go.get("boulder#collisionobject", "angular_velocity") -- do something interesting if velocity.z < 0 then -- clockwise rotation ... else -- counter clockwise rotation ... end -- decrease it by 10% velocity.z = velocity.z * 0.9 go.set("boulder#collisionobject", "angular_velocity", velocity * 0.9) ``` ### apply_force *Type:* MESSAGE Post this message to a collision-object-component to apply the specified force on the collision object. The collision object must be dynamic. **Parameters** - `force` (vector3) - the force to be applied on the collision object, measured in Newton - `position` (vector3) - the position where the force should be applied **Examples** Assuming the instance of the script has a collision-object-component with id "co": ``` -- apply a force of 1 Newton towards world-x at the center of the game object instance msg.post("#co", "apply_force", {force = vmath.vector3(1, 0, 0), position = go.get_world_position()}) ``` ### collision_event *Type:* MESSAGE See physics.set_event_listener. This message is sent to a function specified in physics.set_event_listener when two collision objects collide. This message only reports that a collision has occurred and will be sent once per frame and per colliding pair. For more detailed information, check for the contact_point_event. **Parameters** - `a` (table) - collision information for object A
position
vector3 The world position of object A
id
hash The ID of object A
group
hash The collision group of object A
- `b` (table) - collision information for object B
position
vector3 The world position of object B
id
hash The ID of object B
group
hash The collision group of object B
**Examples** How to take action when a collision occurs: ``` physics.set_event_listener(function(self, event, data) if event == hash("collision_event") then pprint(data) -- { -- a = { -- group = hash: [default], -- position = vmath.vector3(183, 666, 0), -- id = hash: [/go1] -- }, -- b = { -- group = hash: [default], -- position = vmath.vector3(185, 704.05865478516, 0), -- id = hash: [/go2] -- } -- } end end) ``` ### collision_response *Type:* MESSAGE This message is broadcasted to every component of an instance that has a collision object, when the collision object collides with another collision object. For a script to take action when such a collision happens, it should check for this message in its on_message callback function. This message only reports that a collision actually happened and will only be sent once per colliding pair and frame. To retrieve more detailed information, check for the contact_point_response instead. **Parameters** - `other_id` (hash) - the id of the instance the collision object collided with - `other_position` (vector3) - the world position of the instance the collision object collided with - `other_group` (hash) - the collision group of the other collision object - `own_group` (hash) - the collision group of the own collision object **Examples** How to take action when a collision occurs: ``` function on_message(self, message_id, message, sender) -- check for the message if message_id == hash("collision_response") then -- take action end end ``` ### contact_point_event *Type:* MESSAGE See physics.set_event_listener. This message is sent to a function specified in physics.set_event_listener when a collision object has contact points with another collision object. Since multiple contact points can occur for two colliding objects, this event can be sent multiple times in the same frame for the same two colliding objects. To only be notified once when the collision occurs, check for the collision_event event instead. **Parameters** - `applied_impulse` (number) - the impulse the contact resulted in - `distance` (number) - the penetration distance between the objects, which is always positive - `a` (table) - contact point information for object A
position
vector3 The world position of object A
id
hash The ID of object A
group
hash The collision group of object A
relative_velocity
vector3 The relative velocity of the collision object A as observed from B object
mass
number The mass of the collision object A in kg
normal
vector3 normal in world space of the contact point, which points from B object towards A object
- `b` (table) - contact point information for object B
position
vector3 The world position of object B
id
hash The ID of object B
group
hash The collision group of object B
relative_velocity
vector3 The relative velocity of the collision object B as observed from A object
mass
number The mass of the collision object B in kg
normal
vector3 normal in world space of the contact point, which points from A object towards B object
**Examples** How to take action when a contact point occurs: ``` physics.set_event_listener(function(self, events) for _,event in ipairs(events): if event['type'] == hash("contact_point_event") then pprint(event) -- { -- applied_impulse = 310.00769042969, -- distance = 0.0714111328125, -- a = { -- position = vmath.vector3(446, 371, 0), -- relative_velocity = vmath.vector3(1.1722083854693e-06, -20.667181015015, -0), -- mass = 0, -- group = hash: [default], -- id = hash: [/flat], -- normal = vmath.vector3(-0, -1, -0) -- }, -- b = { -- position = vmath.vector3(185, 657.92858886719, 0), -- relative_velocity = vmath.vector3(-1.1722083854693e-06, 20.667181015015, 0), -- mass = 10, -- group = hash: [default], -- id = hash: [/go2], -- normal = vmath.vector3(0, 1, 0) -- }, -- type = hash: [contact_point_event] -- } end end end) ``` ### contact_point_response *Type:* MESSAGE This message is broadcasted to every component of an instance that has a collision object, when the collision object has contact points with respect to another collision object. For a script to take action when such contact points occur, it should check for this message in its on_message callback function. Since multiple contact points can occur for two colliding objects, this message can be sent multiple times in the same frame for the same two colliding objects. To only be notified once when the collision occurs, check for the collision_response message instead. **Parameters** - `position` (vector3) - world position of the contact point - `normal` (vector3) - normal in world space of the contact point, which points from the other object towards the current object - `relative_velocity` (vector3) - the relative velocity of the collision object as observed from the other object - `distance` (number) - the penetration distance between the objects, which is always positive - `applied_impulse` (number) - the impulse the contact resulted in - `life_time` (number) - life time of the contact, not currently used - `mass` (number) - the mass of the current collision object in kg - `other_mass` (number) - the mass of the other collision object in kg - `other_id` (hash) - the id of the instance the collision object is in contact with - `other_position` (vector3) - the world position of the other collision object - `other_group` (hash) - the collision group of the other collision object - `own_group` (hash) - the collision group of the own collision object **Examples** How to take action when a contact point occurs: ``` function on_message(self, message_id, message, sender) -- check for the message if message_id == hash("contact_point_response") then -- take action end end ``` ### linear_damping *Type:* PROPERTY The linear damping value for the collision object. Setting this value alters the damping of linear motion of the object. Valid values are between 0 (no damping) and 1 (full damping). **Examples** How to increase a collision object component's linear damping: ``` -- get linear damping from collision object "collisionobject" in gameobject "floater" local target = "floater#collisionobject" local damping = go.get(target, "linear_damping") -- increase it by 10% if it's below 0.9 if damping <= 0.9 then go.set(target, "linear_damping", damping * 1.1) end ``` ### linear_velocity *Type:* PROPERTY The current linear velocity of the collision object component as a vector3. The velocity is measured in units/s (pixels/s). **Replaces:** request_velocity and velocity_response **Examples** How to query and modify a collision object component's linear velocity: ``` -- get linear velocity from collision object "collisionobject" in gameobject "ship" local source = "ship#collisionobject" local velocity = go.get(source, "linear_velocity") -- decrease it by 10% go.set(source, "linear_velocity", velocity * 0.9) -- apply the velocity on target game object "boulder"'s collision object as a force local target = "boulder#collisionobject" local pos = go.get_position(target) msg.post(target, "apply_force", { force = velocity, position = pos }) ``` ### mass *Type:* PROPERTY READ ONLY Returns the defined physical mass of the collision object component as a number. **Examples** How to query a collision object component's mass: ``` -- get mass from collision object component "boulder" local mass = go.get("#boulder", "mass") -- do something useful assert(mass > 1) ``` ### physics.create_joint *Type:* FUNCTION Create a physics joint between two collision object components. Note: Currently only supported in 2D physics. **Parameters** - `joint_type` (number) - the joint type - `collisionobject_a` (string | hash | url) - first collision object - `joint_id` (string | hash) - id of the joint - `position_a` (vector3) - local position where to attach the joint on the first collision object - `collisionobject_b` (string | hash | url) - second collision object - `position_b` (vector3) - local position where to attach the joint on the second collision object - `properties` (table) (optional) - optional joint specific properties table See each joint type for possible properties field. The one field that is accepted for all joint types is: - boolean collide_connected: Set this flag to true if the attached bodies should collide. ### physics.destroy_joint *Type:* FUNCTION Destroy an already physics joint. The joint has to be created before a destroy can be issued. Note: Currently only supported in 2D physics. **Parameters** - `collisionobject` (string | hash | url) - collision object where the joint exist - `joint_id` (string | hash) - id of the joint ### physics.get_gravity *Type:* FUNCTION Get the gravity in runtime. The gravity returned is not global, it will return the gravity for the collection that the function is called from. Note: For 2D physics the z component will always be zero. **Returns** - `gravity` (vector3) - gravity vector of collection **Examples** ``` function init(self) local gravity = physics.get_gravity() -- Inverse gravity! gravity = -gravity physics.set_gravity(gravity) end ``` ### physics.get_group *Type:* FUNCTION Returns the group name of a collision object as a hash. **Parameters** - `url` (string | hash | url) - the collision object to return the group of. **Returns** - `group` (hash) - hash value of the group.
local function check_is_enemy()
    local group = physics.get_group("#collisionobject")
    return group == hash("enemy")
end
### physics.get_joint_properties *Type:* FUNCTION Get a table for properties for a connected joint. The joint has to be created before properties can be retrieved. Note: Currently only supported in 2D physics. **Parameters** - `collisionobject` (string | hash | url) - collision object where the joint exist - `joint_id` (string | hash) - id of the joint **Returns** - `properties` (table) - properties table. See the joint types for what fields are available, the only field available for all types is:
  • boolean collide_connected: Set this flag to true if the attached bodies should collide.
### physics.get_joint_reaction_force *Type:* FUNCTION Get the reaction force for a joint. The joint has to be created before the reaction force can be calculated. Note: Currently only supported in 2D physics. **Parameters** - `collisionobject` (string | hash | url) - collision object where the joint exist - `joint_id` (string | hash) - id of the joint **Returns** - `force` (vector3) - reaction force for the joint ### physics.get_joint_reaction_torque *Type:* FUNCTION Get the reaction torque for a joint. The joint has to be created before the reaction torque can be calculated. Note: Currently only supported in 2D physics. **Parameters** - `collisionobject` (string | hash | url) - collision object where the joint exist - `joint_id` (string | hash) - id of the joint **Returns** - `torque` (number) - the reaction torque on bodyB in N*m. ### physics.get_maskbit *Type:* FUNCTION Returns true if the specified group is set in the mask of a collision object, false otherwise. **Parameters** - `url` (string | hash | url) - the collision object to check the mask of. - `group` (string) - the name of the group to check for. **Returns** - `maskbit` (boolean) - boolean value of the maskbit. 'true' if present, 'false' otherwise.
local function is_invincible()
    -- check if the collisionobject would collide with the "bullet" group
    local invincible = physics.get_maskbit("#collisionobject", "bullet")
    return invincible
end
### physics.get_shape *Type:* FUNCTION Gets collision shape data from a collision object **Parameters** - `url` (string | hash | url) - the collision object. - `shape` (string | hash) - the name of the shape to get data for. **Returns** - `table` (table) - A table containing meta data about the physics shape
type
number The shape type. Supported values:
  • physics.SHAPE_TYPE_SPHERE
  • physics.SHAPE_TYPE_BOX
  • physics.SHAPE_TYPE_CAPSULE Only supported for 3D physics
  • physics.SHAPE_TYPE_HULL
The returned table contains different fields depending on which type the shape is. If the shape is a sphere:
diameter
number the diameter of the sphere shape
If the shape is a box:
dimensions
vector3 a vmath.vector3 of the box dimensions
If the shape is a capsule:
diameter
number the diameter of the capsule poles
height
number the height of the capsule
local function get_shape_meta()
    local sphere = physics.get_shape("#collisionobject", "my_sphere_shape")
    -- returns a table with sphere.diameter
    return sphere
end
### physics.JOINT_TYPE_FIXED *Type:* CONSTANT The following properties are available when connecting a joint of JOINT_TYPE_FIXED type: **Parameters** - `max_length` (number) - The maximum length of the rope. ### physics.JOINT_TYPE_HINGE *Type:* CONSTANT The following properties are available when connecting a joint of JOINT_TYPE_HINGE type: **Parameters** - `reference_angle` (number) - The bodyB angle minus bodyA angle in the reference state (radians). - `lower_angle` (number) - The lower angle for the joint limit (radians). - `upper_angle` (number) - The upper angle for the joint limit (radians). - `max_motor_torque` (number) - The maximum motor torque used to achieve the desired motor speed. Usually in N-m. - `motor_speed` (number) - The desired motor speed. Usually in radians per second. - `enable_limit` (boolean) - A flag to enable joint limits. - `enable_motor` (boolean) - A flag to enable the joint motor. - `joint_angle` (number) - READ ONLYCurrent joint angle in radians. (Read only field, available from physics.get_joint_properties()) - `joint_speed` (number) - READ ONLYCurrent joint angle speed in radians per second. (Read only field, available from physics.get_joint_properties()) ### physics.JOINT_TYPE_SLIDER *Type:* CONSTANT The following properties are available when connecting a joint of JOINT_TYPE_SLIDER type: **Parameters** - `local_axis_a` (vector3) - The local translation unit axis in bodyA. - `reference_angle` (number) - The constrained angle between the bodies: bodyB_angle - bodyA_angle. - `enable_limit` (boolean) - Enable/disable the joint limit. - `lower_translation` (number) - The lower translation limit, usually in meters. - `upper_translation` (number) - The upper translation limit, usually in meters. - `enable_motor` (boolean) - Enable/disable the joint motor. - `max_motor_force` (number) - The maximum motor torque, usually in N-m. - `motor_speed` (number) - The desired motor speed in radians per second. - `joint_translation` (number) - READ ONLYCurrent joint translation, usually in meters. (Read only field, available from physics.get_joint_properties()) - `joint_speed` (number) - READ ONLYCurrent joint translation speed, usually in meters per second. (Read only field, available from physics.get_joint_properties()) ### physics.JOINT_TYPE_SPRING *Type:* CONSTANT The following properties are available when connecting a joint of JOINT_TYPE_SPRING type: **Parameters** - `length` (number) - The natural length between the anchor points. - `frequency` (number) - The mass-spring-damper frequency in Hertz. A value of 0 disables softness. - `damping` (number) - The damping ratio. 0 = no damping, 1 = critical damping. ### physics.JOINT_TYPE_WELD *Type:* CONSTANT The following properties are available when connecting a joint of JOINT_TYPE_WELD type: **Parameters** - `reference_angle` (number) - READ ONLYThe bodyB angle minus bodyA angle in the reference state (radians). - `frequency` (number) - The mass-spring-damper frequency in Hertz. Rotation only. Disable softness with a value of 0. - `damping` (number) - The damping ratio. 0 = no damping, 1 = critical damping. ### physics.JOINT_TYPE_WHEEL *Type:* CONSTANT The following properties are available when connecting a joint of JOINT_TYPE_WHEEL type: **Parameters** - `local_axis_a` (vector3) - The local translation unit axis in bodyA. - `max_motor_torque` (number) - The maximum motor torque used to achieve the desired motor speed. Usually in N-m. - `motor_speed` (number) - The desired motor speed in radians per second. - `enable_motor` (boolean) - Enable/disable the joint motor. - `frequency` (number) - The mass-spring-damper frequency in Hertz. Rotation only. Disable softness with a value of 0. - `damping` (number) - The spring damping ratio. 0 = no damping, 1 = critical damping. - `joint_translation` (number) - READ ONLYCurrent joint translation, usually in meters. (Read only field, available from physics.get_joint_properties()) - `joint_speed` (number) - READ ONLYCurrent joint translation speed, usually in meters per second. (Read only field, available from physics.get_joint_properties()) ### physics.raycast *Type:* FUNCTION Ray casts are used to test for intersections against collision objects in the physics world. Collision objects of types kinematic, dynamic and static are tested against. Trigger objects do not intersect with ray casts. Which collision objects to hit is filtered by their collision groups and can be configured through groups. NOTE: Ray casts will ignore collision objects that contain the starting point of the ray. This is a limitation in Box2D. **Parameters** - `from` (vector3) - the world position of the start of the ray - `to` (vector3) - the world position of the end of the ray - `groups` (table) - a lua table containing the hashed groups for which to test collisions against - `options` (table) (optional) - a lua table containing options for the raycast.
all
boolean Set to true to return all ray cast hits. If false, it will only return the closest hit.
**Returns** - `result` (table | nil) - It returns a list. If missed it returns nil. See ray_cast_response for details on the returned values. **Examples** How to perform a ray cast synchronously: ``` function init(self) self.groups = {hash("world"), hash("enemy")} end function update(self, dt) -- request ray cast local result = physics.raycast(from, to, self.groups, {all=true}) if result ~= nil then -- act on the hit (see 'ray_cast_response') for _,result in ipairs(results) do handle_result(result) end end end ``` ### physics.raycast_async *Type:* FUNCTION Ray casts are used to test for intersections against collision objects in the physics world. Collision objects of types kinematic, dynamic and static are tested against. Trigger objects do not intersect with ray casts. Which collision objects to hit is filtered by their collision groups and can be configured through groups. The actual ray cast will be performed during the physics-update. If an object is hit, the result will be reported via a ray_cast_response message. If there is no object hit, the result will be reported via a ray_cast_missed message. NOTE: Ray casts will ignore collision objects that contain the starting point of the ray. This is a limitation in Box2D. **Parameters** - `from` (vector3) - the world position of the start of the ray - `to` (vector3) - the world position of the end of the ray - `groups` (table) - a lua table containing the hashed groups for which to test collisions against - `request_id` (number) (optional) - a number in range [0,255]. It will be sent back in the response for identification, 0 by default **Examples** How to perform a ray cast asynchronously: ``` function init(self) self.my_groups = {hash("my_group1"), hash("my_group2")} end function update(self, dt) -- request ray cast physics.raycast_async(my_start, my_end, self.my_groups) end function on_message(self, message_id, message, sender) -- check for the response if message_id == hash("ray_cast_response") then -- act on the hit elseif message_id == hash("ray_cast_missed") then -- act on the miss end end ``` ### physics.set_event_listener *Type:* FUNCTION Only one physics world event listener can be set at a time. **Parameters** - `callback` (function(self, events) | nil) - A callback that receives an information about all the physics interactions in this physics world.
self
object The calling script
event
constant The type of event. Can be one of these messages:
data
table The callback value data is a table that contains event-related data. See the documentation for details on the messages.
**Examples** ``` local function physics_world_listener(self, events) for _,event in ipairs(events): local event_type = event['type'] if event_type == hash("contact_point_event") then pprint(event) -- { -- distance = 2.1490633487701, -- applied_impulse = 0 -- a = { --[[0x113f7c6c0]] -- group = hash: [box], -- id = hash: [/box] -- mass = 0, -- normal = vmath.vector3(0.379, 0.925, -0), -- position = vmath.vector3(517.337, 235.068, 0), -- instance_position = vmath.vector3(480, 144, 0), -- relative_velocity = vmath.vector3(-0, -0, -0), -- }, -- b = { --[[0x113f7c840]] -- group = hash: [circle], -- id = hash: [/circle] -- mass = 0, -- normal = vmath.vector3(-0.379, -0.925, 0), -- position = vmath.vector3(517.337, 235.068, 0), -- instance_position = vmath.vector3(-0.0021, 0, -0.0022), -- relative_velocity = vmath.vector3(0, 0, 0), -- }, -- } elseif event == hash("collision_event") then pprint(event) -- { -- a = { -- group = hash: [default], -- position = vmath.vector3(183, 666, 0), -- id = hash: [/go1] -- }, -- b = { -- group = hash: [default], -- position = vmath.vector3(185, 704.05865478516, 0), -- id = hash: [/go2] -- } -- } elseif event == hash("trigger_event") then pprint(event) -- { -- enter = true, -- b = { -- group = hash: [default], -- id = hash: [/go2] -- }, -- a = { -- group = hash: [default], -- id = hash: [/go1] -- } -- }, elseif event == hash("ray_cast_response") then pprint(event) --{ -- group = hash: [default], -- request_id = 0, -- position = vmath.vector3(249.92222595215, 249.92222595215, 0), -- fraction = 0.68759721517563, -- normal = vmath.vector3(0, 1, 0), -- id = hash: [/go] -- } elseif event == hash("ray_cast_missed") then pprint(event) -- { -- request_id = 0 --}, end end function init(self) physics.set_event_listener(physics_world_listener) end ``` ### physics.set_gravity *Type:* FUNCTION Set the gravity in runtime. The gravity change is not global, it will only affect the collection that the function is called from. Note: For 2D physics the z component of the gravity vector will be ignored. **Parameters** - `gravity` (vector3) - the new gravity vector **Examples** ``` function init(self) -- Set "upside down" gravity for this collection. physics.set_gravity(vmath.vector3(0, 10.0, 0)) end ``` ### physics.set_group *Type:* FUNCTION Updates the group property of a collision object to the specified string value. The group name should exist i.e. have been used in a collision object in the editor. **Parameters** - `url` (string | hash | url) - the collision object affected. - `group` (string) - the new group name to be assigned.
local function change_collision_group()
     physics.set_group("#collisionobject", "enemy")
end
### physics.set_hflip *Type:* FUNCTION Flips the collision shapes horizontally for a collision object **Parameters** - `url` (string | hash | url) - the collision object that should flip its shapes - `flip` (boolean) - true if the collision object should flip its shapes, false if not **Examples** ``` function init(self) self.fliph = true -- set on some condition physics.set_hflip("#collisionobject", self.fliph) end ``` ### physics.set_joint_properties *Type:* FUNCTION Updates the properties for an already connected joint. The joint has to be created before properties can be changed. Note: Currently only supported in 2D physics. **Parameters** - `collisionobject` (string | hash | url) - collision object where the joint exist - `joint_id` (string | hash) - id of the joint - `properties` (table) - joint specific properties table Note: The collide_connected field cannot be updated/changed after a connection has been made. ### physics.set_maskbit *Type:* FUNCTION Sets or clears the masking of a group (maskbit) in a collision object. **Parameters** - `url` (string | hash | url) - the collision object to change the mask of. - `group` (string) - the name of the group (maskbit) to modify in the mask. - `maskbit` (boolean) - boolean value of the new maskbit. 'true' to enable, 'false' to disable.
local function make_invincible()
    -- no longer collide with the "bullet" group
    physics.set_maskbit("#collisionobject", "bullet", false)
end
### physics.set_shape *Type:* FUNCTION Sets collision shape data for a collision object. Please note that updating data in 3D can be quite costly for box and capsules. Because of the physics engine, the cost comes from having to recreate the shape objects when certain shapes needs to be updated. **Parameters** - `url` (string | hash | url) - the collision object. - `shape` (string | hash) - the name of the shape to get data for. - `table` (table) - the shape data to update the shape with. See physics.get_shape for a detailed description of each field in the data table.
local function set_shape_data()
    -- set capsule shape data
    local data = {}
    data.type = physics.SHAPE_TYPE_CAPSULE
    data.diameter = 10
    data.height = 20
    physics.set_shape("#collisionobject", "my_capsule_shape", data)

    -- set sphere shape data
    data = {}
    data.type = physics.SHAPE_TYPE_SPHERE
    data.diameter = 10
    physics.set_shape("#collisionobject", "my_sphere_shape", data)

    -- set box shape data
    data = {}
    data.type = physics.SHAPE_TYPE_BOX
    data.dimensions = vmath.vector3(10, 10, 5)
    physics.set_shape("#collisionobject", "my_box_shape", data)
end
### physics.set_vflip *Type:* FUNCTION Flips the collision shapes vertically for a collision object **Parameters** - `url` (string | hash | url) - the collision object that should flip its shapes - `flip` (boolean) - true if the collision object should flip its shapes, false if not **Examples** ``` function init(self) self.flipv = true -- set on some condition physics.set_vflip("#collisionobject", self.flipv) end ``` ### physics.SHAPE_TYPE_BOX *Type:* CONSTANT ### physics.SHAPE_TYPE_CAPSULE *Type:* CONSTANT ### physics.SHAPE_TYPE_HULL *Type:* CONSTANT ### physics.SHAPE_TYPE_SPHERE *Type:* CONSTANT ### physics.update_mass *Type:* FUNCTION The function recalculates the density of each shape based on the total area of all shapes and the specified mass, then updates the mass of the body accordingly. Note: Currently only supported in 2D physics. **Parameters** - `collisionobject` (string | hash | url) - the collision object whose mass needs to be updated. - `mass` (number) - the new mass value to set for the collision object. **Examples** ``` physics.update_mass("#collisionobject", 14) ``` ### physics.wakeup *Type:* FUNCTION Collision objects tend to fall asleep when inactive for a small period of time for efficiency reasons. This function wakes them up. **Parameters** - `url` (string | hash | url) - the collision object to wake.
function on_input(self, action_id, action)
    if action_id == hash("test") and action.pressed then
        physics.wakeup("#collisionobject")
    end
end
### ray_cast_missed *Type:* MESSAGE This message is sent back to the sender of a ray_cast_request, or to the physics world listener if it is set (see physics.set_event_listener), if the ray didn't hit any collision object. See physics.raycast_async for examples of how to use it. **Parameters** - `request_id` (number) - id supplied when the ray cast was requested ### ray_cast_response *Type:* MESSAGE This message is sent back to the sender of a ray_cast_request, or to the physics world listener if it is set (see physics.set_event_listener), if the ray hits a collision object. See physics.raycast_async for examples of how to use it. **Parameters** - `fraction` (number) - the fraction of the hit measured along the ray, where 0 is the start of the ray and 1 is the end - `position` (vector3) - the world position of the hit - `normal` (vector3) - the normal of the surface of the collision object where it was hit - `id` (hash) - the instance id of the hit collision object - `group` (hash) - the collision group of the hit collision object as a hashed name - `request_id` (number) - id supplied when the ray cast was requested ### trigger_event *Type:* MESSAGE See physics.set_event_listener. This message is sent to a function specified in physics.set_event_listener when a collision object interacts with another collision object and one of them is a trigger. This message only reports that an interaction actually happened and will be sent once per colliding pair and frame. For more detailed information, check for the contact_point_event. **Parameters** - `enter` (boolean) - if the interaction was an entry or not - `a` (table) -
interaction information for object A
id
hash The ID of object A
group
hash The collision group of object A
- `b` (table) - collision information for object B
id
hash The ID of object B
group
hash The collision group of object B
**Examples** How to take action when a trigger interaction occurs: ``` physics.set_event_listener(function(self, event, data) if event == hash("trigger_event") then if data.enter then -- take action for entry else -- take action for exit end pprint(data) -- { -- enter = true, -- b = { -- group = hash: [default], -- id = hash: [/go2] -- }, -- a = { -- group = hash: [default], -- id = hash: [/go1] -- } -- }, end end) ``` ### trigger_response *Type:* MESSAGE This message is broadcasted to every component of an instance that has a collision object, when the collision object interacts with another collision object and one of them is a trigger. For a script to take action when such an interaction happens, it should check for this message in its on_message callback function. This message only reports that an interaction actually happened and will only be sent once per colliding pair and frame. To retrieve more detailed information, check for the contact_point_response instead. **Parameters** - `other_id` (hash) - the id of the instance the collision object collided with - `enter` (boolean) - if the interaction was an entry or not - `other_group` (hash) - the collision group of the triggering collision object - `own_group` (hash) - the collision group of the own collision object **Examples** How to take action when a trigger interaction occurs: ``` function on_message(self, message_id, message, sender) -- check for the message if message_id == hash("trigger_response") then if message.enter then -- take action for entry else -- take action for exit end end end ``` # Profiler {#apis:profiler-lua} **Namespace:** `profiler` **Language:** Lua **Type:** Defold Lua **File:** `profiler.cpp` **Source:** `engine/profiler/src/profiler.cpp` Functions for getting profiling data in runtime. More detailed [profiling](https://www.defold.com/manuals/profiling/) and [debugging](http://www.defold.com/manuals/debugging/) information available in the manuals. ## API ### profiler.dump_frame *Type:* FUNCTION logs the current frame to the console **Examples** ``` profiler.dump_frame() ``` ### profiler.enable *Type:* FUNCTION The profiler is a real-time tool that shows the numbers of milliseconds spent in each scope per frame as well as counters. The profiler is very useful for tracking down performance and resource problems. **Parameters** - `enabled` (boolean) - true to enable, false to disable **Examples** ``` -- Show the profiler UI profiler.enable(true) ``` ### profiler.enable_ui *Type:* FUNCTION Creates and shows or hides and destroys the on-sceen profiler ui The profiler is a real-time tool that shows the numbers of milliseconds spent in each scope per frame as well as counters. The profiler is very useful for tracking down performance and resource problems. **Parameters** - `enabled` (boolean) - true to enable, false to disable **Examples** ``` -- Show the profiler UI profiler.enable_ui(true) ``` ### profiler.get_cpu_usage *Type:* FUNCTION Get the percent of CPU usage by the application, as reported by the OS. This function is not available on HTML5. For some platforms ( Android, Linux and Windows), this information is only available by default in the debug version of the engine. It can be enabled in release version as well by checking track_cpu under profiler in the game.project file. (This means that the engine will sample the CPU usage in intervalls during execution even in release mode.) **Returns** - `percent` (number) - of CPU used by the application ### profiler.get_memory_usage *Type:* FUNCTION Get the amount of memory used (resident/working set) by the application in bytes, as reported by the OS. This function is not available on HTML5. The values are gathered from internal OS functions which correspond to the following; OS Value iOS MacOSAndroid Linux Resident memory Windows Working set HTML5 Not available **Returns** - `bytes` (number) - used by the application **Examples** Get memory usage before and after loading a collection: ``` print(profiler.get_memory_usage()) msg.post("#collectionproxy", "load") ... print(profiler.get_memory_usage()) -- will report a higher number than the initial call ``` ### profiler.log_text *Type:* FUNCTION Send a text to the connected profiler **Parameters** - `text` (string) - the string to send to the connected profiler **Examples** ``` profiler.log_text("Event: " .. name) ``` ### profiler.MODE_PAUSE *Type:* CONSTANT pause on current frame ### profiler.MODE_RECORD *Type:* CONSTANT start recording ### profiler.MODE_RUN *Type:* CONSTANT continously show latest frame ### profiler.MODE_SHOW_PEAK_FRAME *Type:* CONSTANT pause at peak frame ### profiler.recorded_frame_count *Type:* FUNCTION Get the number of recorded frames in the on-screen profiler ui recording buffer **Returns** - `frame_count` (number) - the number of recorded frames, zero if on-screen profiler is disabled **Examples** ``` -- Show the last recorded frame local recorded_frame_count = profiler.recorded_frame_count() profiler.view_recorded_frame(recorded_frame_count) ``` ### profiler.scope_begin *Type:* FUNCTION Starts a profile scope. **Notes** - Must be correctly matched with a corresponding call to `profiler.scope_end()` in the same frame. Any scopes left open at the end of the frame are reported as errors and auto-closed. **Parameters** - `name` (string) - The name of the scope **Examples** ``` -- Go back one frame profiler.scope_begin("test_function") test_function() profiler.scope_end() ``` ### profiler.scope_end *Type:* FUNCTION End the current profile scope. **Notes** - Calling this without a matching `profiler.scope_begin()` raises a Lua error. ### profiler.set_ui_mode *Type:* FUNCTION Set the on-screen profile mode - run, pause, record or show peak frame **Parameters** - `mode` (constant) - the mode to set the ui profiler in
  • profiler.MODE_RUN This is default mode that continously shows the last frame
  • profiler.MODE_PAUSE Pauses on the currently displayed frame
  • profiler.MODE_SHOW_PEAK_FRAME Pauses on the currently displayed frame but shows a new frame if that frame is slower
  • profiler.MODE_RECORD Records all incoming frames to the recording buffer
To stop recording, switch to a different mode such as MODE_PAUSE or MODE_RUN. You can also use the view_recorded_frame function to display a recorded frame. Doing so stops the recording as well. Every time you switch to recording mode the recording buffer is cleared. **Examples** ``` function start_recording() profiler.set_ui_mode(profiler.MODE_RECORD) end function stop_recording() profiler.set_ui_mode(profiler.MODE_PAUSE) end ``` ### profiler.set_ui_view_mode *Type:* FUNCTION Set the on-screen profile view mode - minimized or expanded **Parameters** - `mode` (constant) - the view mode to set the ui profiler in
  • profiler.VIEW_MODE_FULL The default mode which displays all the ui profiler details
  • profiler.VIEW_MODE_MINIMIZED Minimized mode which only shows the top header (fps counters and ui profiler mode)
**Examples** ``` -- Minimize the profiler view profiler.set_ui_view_mode(profiler.VIEW_MODE_MINIMIZED) ``` ### profiler.set_ui_vsync_wait_visible *Type:* FUNCTION Shows or hides the time the engine waits for vsync in the on-screen profiler Each frame the engine waits for vsync and depending on your vsync settings and how much time your game logic takes this time can dwarf the time in the game logic making it hard to see details in the on-screen profiler graph and lists. Also, by hiding this the FPS times in the header show the time spent each time excuding the time spent waiting for vsync. This shows you how long time your game is spending actively working each frame. This setting also effects the display of recorded frames but does not affect the actual recorded frames so it is possible to toggle this on and off when viewing recorded frames. By default the vsync wait times is displayed in the profiler. **Parameters** - `visible` (boolean) - true to include it in the display, false to hide it. **Examples** ``` -- Exclude frame wait time form the profiler ui profiler.set_ui_vsync_wait_visible(false) ``` ### profiler.VIEW_MODE_FULL *Type:* CONSTANT show full profiler ui ### profiler.VIEW_MODE_MINIMIZED *Type:* CONSTANT show mimimal profiler ui ### profiler.view_recorded_frame *Type:* FUNCTION Pauses and displays a frame from the recording buffer in the on-screen profiler ui The frame to show can either be an absolute frame or a relative frame to the current frame. **Parameters** - `frame_index` (table) - a table where you specify one of the following parameters:
  • distance The offset from the currently displayed frame (this is truncated between zero and the number of recorded frames)
  • frame The frame index in the recording buffer (1 is first recorded frame)
**Examples** ``` -- Go back one frame profiler.view_recorded_frame({distance = -1}) ``` # Render {#apis:render-lua} **Namespace:** `render` **Language:** Lua **Type:** Defold Lua **File:** `render_ddf.proto` **Source:** `engine/render/proto/render/render_ddf.proto` Rendering API documentation ## API ### clear_color *Type:* MESSAGE Set render clear color. This is the color that appears on the screen where nothing is rendered, i.e. background. **Parameters** - `color` (vector4) - color to use as clear color **Examples** ``` msg.post("@render:", "clear_color", { color = vmath.vector4(1, 0, 0, 0) } ) ``` ### constant_buffer *Type:* TYPEDEF Constant buffer **Parameters** - `value` (userdata) ### draw_debug_text *Type:* MESSAGE Draw a text on the screen. This should be used for debugging purposes only. **Parameters** - `position` (vector3) - position of the text - `text` (string) - the text to draw - `color` (vector4) - color of the text **Examples** ``` msg.post("@render:", "draw_debug_text", { text = "Hello world!", position = vmath.vector3(200, 200, 0), color = vmath.vector4(1, 0, 0, 1) } ) ``` ### draw_line *Type:* MESSAGE Draw a line on the screen. This should mostly be used for debugging purposes. **Parameters** - `start_point` (vector3) - start point of the line - `end_point` (vector3) - end point of the line - `color` (vector4) - color of the line **Examples** ``` -- draw a white line from (200, 200) to (200, 300) msg.post("@render:", "draw_line", { start_point = vmath.vector3(200, 200, 0), end_point = vmath.vector3(200, 300, 0), color = vmath.vector4(1, 1, 1, 1) } ) ``` ### render.clear *Type:* FUNCTION Clear buffers in the currently enabled render target with specified value. If the render target has been created with multiple color attachments, all buffers will be cleared with the same value. **Parameters** - `buffers` (table) - table with keys specifying which buffers to clear and values set to clear values. Available keys are:
  • graphics.BUFFER_TYPE_COLOR0_BIT
  • graphics.BUFFER_TYPE_DEPTH_BIT
  • graphics.BUFFER_TYPE_STENCIL_BIT
**Examples** Clear the color buffer and the depth buffer. ``` render.clear({[graphics.BUFFER_TYPE_COLOR0_BIT] = vmath.vector4(0, 0, 0, 0), [graphics.BUFFER_TYPE_DEPTH_BIT] = 1}) ``` ### render.constant_buffer *Type:* FUNCTION Constant buffers are used to set shader program variables and are optionally passed to the render.draw() function. The buffer's constant elements can be indexed like an ordinary Lua table, but you can't iterate over them with pairs() or ipairs(). **Returns** - `buffer` (constant_buffer) - new constant buffer **Examples** Set a "tint" constant in a constant buffer in the render script: ``` local constants = render.constant_buffer() constants.tint = vmath.vector4(1, 1, 1, 1) ``` Then use the constant buffer when drawing a predicate: ``` render.draw(self.my_pred, {constants = constants}) ``` The constant buffer also supports array values by specifying constants in a table: ``` local constants = render.constant_buffer() constants.light_colors = {} constants.light_colors[1] = vmath.vector4(1, 0, 0, 1) constants.light_colors[2] = vmath.vector4(0, 1, 0, 1) constants.light_colors[3] = vmath.vector4(0, 0, 1, 1) ``` You can also create the table by passing the vectors directly when creating the table: ``` local constants = render.constant_buffer() constants.light_colors = { vmath.vector4(1, 0, 0, 1) vmath.vector4(0, 1, 0, 1) vmath.vector4(0, 0, 1, 1) } -- Add more constant to the array constants.light_colors[4] = vmath.vector4(1, 1, 1, 1) ``` ### render.delete_render_target *Type:* FUNCTION Deletes a render target created by a render script. You cannot delete a render target resource. **Parameters** - `render_target` (render_target) - render target to delete **Examples** How to delete a render target: ``` render.delete_render_target(self.my_render_target) ``` ### render.disable_material *Type:* FUNCTION If a material is currently enabled, disable it. The name of the material must be specified in the ".render" resource set in the "game.project" setting. **Examples** Enable material named "glow", then draw my_pred with it. ``` render.enable_material("glow") render.draw(self.my_pred) render.disable_material() ``` ### render.disable_state *Type:* FUNCTION Disables a render state. **Parameters** - `state` (constant) - state to disable
  • graphics.STATE_DEPTH_TEST
  • graphics.STATE_STENCIL_TEST
  • graphics.STATE_BLEND
  • graphics.STATE_ALPHA_TEST ( not available on iOS and Android)
  • graphics.STATE_CULL_FACE
  • graphics.STATE_POLYGON_OFFSET_FILL
**Examples** Disable face culling when drawing the tile predicate: ``` render.disable_state(graphics.STATE_CULL_FACE) render.draw(self.tile_pred) ``` ### render.disable_texture *Type:* FUNCTION Disables a texture that has previourly been enabled. **Parameters** - `binding` (texture | string | hash) - texture binding, either by texture unit, string or hash that should be disabled **Examples** ``` function update(self, dt) render.enable_texture(0, self.my_render_target, graphics.BUFFER_TYPE_COLOR0_BIT) -- draw a predicate with the render target available as texture 0 in the predicate -- material shader. render.draw(self.my_pred) -- done, disable the texture render.disable_texture(0) end ``` ### render.dispatch_compute *Type:* FUNCTION Dispatches the currently enabled compute program. The dispatch call takes three arguments x,y,z which constitutes the 'global working group' of the compute dispatch. Together with the 'local working group' specified in the compute shader as a layout qualifier, these two sets of parameters forms the number of invocations the compute shader will execute. An optional constant buffer can be provided to override the default constants. If no constants buffer is provided, a default system constants buffer is used containing constants as defined in the compute program. **Parameters** - `x` (number) - global work group size X - `y` (number) - global work group size Y - `z` (number) - global work group size Z - `options` (table) (optional) - optional table with properties:
constants
constant_buffer optional constants to use while rendering
**Examples** ``` function init(self) local color_params = { format = graphics.TEXTURE_FORMAT_RGBA, width = render.get_window_width(), height = render.get_window_height()} self.scene_rt = render.render_target({[graphics.BUFFER_TYPE_COLOR0_BIT] = color_params}) end function update(self, dt) render.set_compute("bloom") render.enable_texture(0, self.backing_texture) render.enable_texture(1, self.scene_rt) render.dispatch_compute(128, 128, 1) render.set_compute() end ``` Dispatch a compute program with a constant buffer: ``` local constants = render.constant_buffer() constants.tint = vmath.vector4(1, 1, 1, 1) render.dispatch_compute(32, 32, 32, {constants = constants}) ``` ### render.draw *Type:* FUNCTION Draws all objects that match a specified predicate. An optional constant buffer can be provided to override the default constants. If no constants buffer is provided, a default system constants buffer is used containing constants as defined in materials and set through go.set (or particlefx.set_constant) on visual components. **Parameters** - `predicate` (number) - predicate to draw for - `options` (table) (optional) - optional table with properties:
frustum
matrix4 A frustum matrix used to cull renderable items. (E.g. local frustum = proj * view). default=nil
frustum_planes
int Determines which sides of the frustum will be used. Default is render.FRUSTUM_PLANES_SIDES.
  • render.FRUSTUM_PLANES_SIDES : The left, right, top and bottom sides of the frustum.
  • render.FRUSTUM_PLANES_ALL : All 6 sides of the frustum.
constants
constant_buffer optional constants to use while rendering
sort_order
int How to sort draw order for world-ordered entries. Default uses the renderer's preferred world sorting (back-to-front).
**Examples** ``` function init(self) -- define a predicate matching anything with material tag "my_tag" self.my_pred = render.predicate({hash("my_tag")}) end function update(self, dt) -- draw everything in the my_pred predicate render.draw(self.my_pred) end ``` Draw predicate with constants: ``` local constants = render.constant_buffer() constants.tint = vmath.vector4(1, 1, 1, 1) render.draw(self.my_pred, {constants = constants}) ``` Draw with predicate and frustum culling (without near+far planes): ``` local frustum = self.proj * self.view render.draw(self.my_pred, {frustum = frustum}) ``` Draw with predicate and frustum culling (with near+far planes): ``` local frustum = self.proj * self.view render.draw(self.my_pred, {frustum = frustum, frustum_planes = render.FRUSTUM_PLANES_ALL}) ``` ### render.draw_debug3d *Type:* FUNCTION Draws all 3d debug graphics such as lines drawn with "draw_line" messages and physics visualization. **Parameters** - `options` (table) (optional) - optional table with properties:
frustum
matrix4 A frustum matrix used to cull renderable items. (E.g. local frustum = proj * view). May be nil.
frustum_planes
int Determines which sides of the frustum will be used. Default is render.FRUSTUM_PLANES_SIDES.
  • render.FRUSTUM_PLANES_SIDES : The left, right, top and bottom sides of the frustum.
  • render.FRUSTUM_PLANES_ALL : All sides of the frustum.
**Replaces:** render.draw_debug2d **Examples** ``` function update(self, dt) -- draw debug visualization render.draw_debug3d() end ``` ### render.enable_material *Type:* FUNCTION If another material was already enabled, it will be automatically disabled and the specified material is used instead. The name of the material must be specified in the ".render" resource set in the "game.project" setting. **Parameters** - `material_id` (string | hash) - material id to enable **Examples** Enable material named "glow", then draw my_pred with it. ``` render.enable_material("glow") render.draw(self.my_pred) render.disable_material() ``` ### render.enable_state *Type:* FUNCTION Enables a particular render state. The state will be enabled until disabled. **Parameters** - `state` (constant) - state to enable
  • graphics.STATE_DEPTH_TEST
  • graphics.STATE_STENCIL_TEST
  • graphics.STATE_BLEND
  • graphics.STATE_ALPHA_TEST ( not available on iOS and Android)
  • graphics.STATE_CULL_FACE
  • graphics.STATE_POLYGON_OFFSET_FILL
**Examples** Enable stencil test when drawing the gui predicate, then disable it: ``` render.enable_state(graphics.STATE_STENCIL_TEST) render.draw(self.gui_pred) render.disable_state(graphics.STATE_STENCIL_TEST) ``` ### render.enable_texture *Type:* FUNCTION Sets the specified texture handle for a render target attachment or a regular texture that should be used for rendering. The texture can be bound to either a texture unit or to a sampler name by a hash or a string. A texture can be bound to multiple units and sampler names at the same time, the actual binding will be applied to the shaders when a shader program is bound. When mixing binding using both units and sampler names, you might end up in situations where two different textures will be applied to the same bind location in the shader. In this case, the texture set to the named sampler will take precedence over the unit. Note that you can bind multiple sampler names to the same texture, in case you want to reuse the same texture for differnt use-cases. It is however recommended that you use the same name everywhere for the textures that should be shared across different materials. **Parameters** - `binding` (number | string | hash) - texture binding, either by texture unit, string or hash for the sampler name that the texture should be bound to - `handle_or_name` (texture | string | hash) - render target or texture handle that should be bound, or a named resource in the "Render Resource" table in the currently assigned .render file - `buffer_type` (graphics.BUFFER_TYPE_COLOR0_BIT | graphics.BUFFER_TYPE_COLOR1_BIT | graphics.BUFFER_TYPE_COLOR2_BIT | graphics.BUFFER_TYPE_COLOR3_BIT | graphics.BUFFER_TYPE_DEPTH_BIT | graphics.BUFFER_TYPE_STENCIL_BIT) (optional) - optional buffer type from which to enable the texture. Note that this argument only applies to render targets. Defaults to graphics.BUFFER_TYPE_COLOR0_BIT. These values are supported:
  • graphics.BUFFER_TYPE_COLOR0_BIT
If The render target has been created as depth and/or stencil textures, these buffer types can be used:
  • graphics.BUFFER_TYPE_DEPTH_BIT
  • graphics.BUFFER_TYPE_STENCIL_BIT
If the render target has been created with multiple color attachments, these buffer types can be used to enable those textures as well. Currently 4 color attachments are supported:
  • graphics.BUFFER_TYPE_COLOR0_BIT
  • graphics.BUFFER_TYPE_COLOR1_BIT
  • graphics.BUFFER_TYPE_COLOR2_BIT
  • graphics.BUFFER_TYPE_COLOR3_BIT
**Examples** ``` function update(self, dt) -- enable target so all drawing is done to it render.set_render_target(self.my_render_target) -- draw a predicate to the render target render.draw(self.my_pred) -- disable target render.set_render_target(render.RENDER_TARGET_DEFAULT) render.enable_texture(0, self.my_render_target, graphics.BUFFER_TYPE_COLOR0_BIT) -- draw a predicate with the render target available as texture 0 in the predicate -- material shader. render.draw(self.my_pred) end ``` ``` function update(self, dt) -- enable render target by resource id render.set_render_target('my_rt_resource') render.draw(self.my_pred) render.set_render_target(render.RENDER_TARGET_DEFAULT) render.enable_texture(0, 'my_rt_resource', graphics.BUFFER_TYPE_COLOR0_BIT) -- draw a predicate with the render target available as texture 0 in the predicate -- material shader. render.draw(self.my_pred) end ``` ``` function update(self, dt) -- bind a texture to the texture unit 0 render.enable_texture(0, self.my_texture_handle) -- bind the same texture to a named sampler render.enable_texture("my_texture_sampler", self.my_texture_handle) end ``` ### render.FRUSTUM_PLANES_ALL *Type:* CONSTANT ### render.FRUSTUM_PLANES_SIDES *Type:* CONSTANT ### render.get_height *Type:* FUNCTION Returns the logical window height that is set in the "game.project" settings. Note that the actual window pixel size can change, either by device constraints or user input. **Returns** - `height` (number) - specified window height **Examples** Get the height of the window ``` local h = render.get_height() ``` ### render.get_render_target_height *Type:* FUNCTION Returns the specified buffer height from a render target. **Parameters** - `render_target` (render_target) - render target from which to retrieve the buffer height - `buffer_type` (graphics.BUFFER_TYPE_COLOR0_BIT | graphics.BUFFER_TYPE_COLOR1_BIT | graphics.BUFFER_TYPE_COLOR2_BIT | graphics.BUFFER_TYPE_COLOR3_BIT | graphics.BUFFER_TYPE_DEPTH_BIT | graphics.BUFFER_TYPE_STENCIL_BIT) - which type of buffer to retrieve the height from
  • graphics.BUFFER_TYPE_COLOR0_BIT
  • graphics.BUFFER_TYPE_DEPTH_BIT
  • graphics.BUFFER_TYPE_STENCIL_BIT
**Returns** - `height` (number) - the height of the render target buffer texture **Examples** ``` -- get the height of the render target color buffer local h = render.get_render_target_height(self.target_right, graphics.BUFFER_TYPE_COLOR0_BIT) -- get the height of a render target resource local w = render.get_render_target_height('my_rt_resource', graphics.BUFFER_TYPE_COLOR0_BIT) ``` ### render.get_render_target_width *Type:* FUNCTION Returns the specified buffer width from a render target. **Parameters** - `render_target` (render_target) - render target from which to retrieve the buffer width - `buffer_type` (graphics.BUFFER_TYPE_COLOR0_BIT | graphics.BUFFER_TYPE_COLOR1_BIT | graphics.BUFFER_TYPE_COLOR2_BIT | graphics.BUFFER_TYPE_COLOR3_BIT | graphics.BUFFER_TYPE_DEPTH_BIT | graphics.BUFFER_TYPE_STENCIL_BIT) - which type of buffer to retrieve the width from
  • graphics.BUFFER_TYPE_COLOR0_BIT
  • graphics.BUFFER_TYPE_COLOR[x]_BIT (x: [0..3], if supported!)
  • graphics.BUFFER_TYPE_DEPTH_BIT
  • graphics.BUFFER_TYPE_STENCIL_BIT
**Returns** - `width` (number) - the width of the render target buffer texture **Examples** ``` -- get the width of the render target color buffer local w = render.get_render_target_width(self.target_right, graphics.BUFFER_TYPE_COLOR0_BIT) -- get the width of a render target resource local w = render.get_render_target_width('my_rt_resource', graphics.BUFFER_TYPE_COLOR0_BIT) ``` ### render.get_width *Type:* FUNCTION Returns the logical window width that is set in the "game.project" settings. Note that the actual window pixel size can change, either by device constraints or user input. **Returns** - `width` (number) - specified window width (number) **Examples** Get the width of the window. ``` local w = render.get_width() ``` ### render.get_window_height *Type:* FUNCTION Returns the actual physical window height. Note that this value might differ from the logical height that is set in the "game.project" settings. **Returns** - `height` (number) - actual window height **Examples** Get the actual height of the window ``` local h = render.get_window_height() ``` ### render.get_window_width *Type:* FUNCTION Returns the actual physical window width. Note that this value might differ from the logical width that is set in the "game.project" settings. **Returns** - `width` (number) - actual window width **Examples** Get the actual width of the window ``` local w = render.get_window_width() ``` ### render.predicate *Type:* FUNCTION This function returns a new render predicate for objects with materials matching the provided material tags. The provided tags are combined into a bit mask for the predicate. If multiple tags are provided, the predicate matches materials with all tags ANDed together. The current limit to the number of tags that can be defined is 64. **Parameters** - `tags` (table) - table of tags that the predicate should match. The tags can be of either hash or string type **Returns** - `predicate` (number) - new predicate **Examples** Create a new render predicate containing all visual objects that have a material with material tags "opaque" AND "smoke". ``` local p = render.predicate({hash("opaque"), hash("smoke")}) ``` ### render.render_target *Type:* FUNCTION Creates a new render target according to the supplied specification table. The table should contain keys specifying which buffers should be created with what parameters. Each buffer key should have a table value consisting of parameters. The following parameter keys are available: Key Values format graphics.TEXTURE_FORMAT_LUMINANCEgraphics.TEXTURE_FORMAT_RGBgraphics.TEXTURE_FORMAT_RGBAgraphics.TEXTURE_FORMAT_DEPTHgraphics.TEXTURE_FORMAT_STENCILgraphics.TEXTURE_FORMAT_RGBA32Fgraphics.TEXTURE_FORMAT_RGBA16F width number height number min_filter (optional) graphics.TEXTURE_FILTER_LINEARgraphics.TEXTURE_FILTER_NEAREST mag_filter (optional) graphics.TEXTURE_FILTER_LINEARgraphics.TEXTURE_FILTER_NEAREST u_wrap (optional) graphics.TEXTURE_WRAP_CLAMP_TO_BORDERgraphics.TEXTURE_WRAP_CLAMP_TO_EDGEgraphics.TEXTURE_WRAP_MIRRORED_REPEATgraphics.TEXTURE_WRAP_REPEAT v_wrap (optional) graphics.TEXTURE_WRAP_CLAMP_TO_BORDERgraphics.TEXTURE_WRAP_CLAMP_TO_EDGEgraphics.TEXTURE_WRAP_MIRRORED_REPEATgraphics.TEXTURE_WRAP_REPEAT flags (optional) render.TEXTURE_BIT (only applicable to depth and stencil buffers) The render target can be created to support multiple color attachments. Each attachment can have different format settings and texture filters, but attachments must be added in sequence, meaning you cannot create a render target at slot 0 and 3. Instead it has to be created with all four buffer types ranging from [0..3] (as denoted by graphics.BUFFER_TYPE_COLORX_BIT where 'X' is the attachment you want to create). It is not guaranteed that the device running the script can support creating render targets with multiple color attachments. To check if the device can support multiple attachments, you can check if the render table contains any of the BUFFER_TYPE_COLOR1_BIT, BUFFER_TYPE_COLOR2_BIT or BUFFER_TYPE_COLOR3_BIT constants: ``` function init(self) if graphics.BUFFER_TYPE_COLOR1_BIT == nil then -- this devices does not support multiple color attachments end end ``` **Parameters** - `name` (string) - render target name - `parameters` (table) - table of buffer parameters, see the description for available keys and values **Returns** - `render_target` (render_target) - new render target **Examples** How to create a new render target and draw to it: ``` function init(self) -- render target buffer parameters local color_params = { format = graphics.TEXTURE_FORMAT_RGBA, width = render.get_window_width(), height = render.get_window_height(), min_filter = graphics.TEXTURE_FILTER_LINEAR, mag_filter = graphics.TEXTURE_FILTER_LINEAR, u_wrap = graphics.TEXTURE_WRAP_CLAMP_TO_EDGE, v_wrap = graphics.TEXTURE_WRAP_CLAMP_TO_EDGE } local depth_params = { format = graphics.TEXTURE_FORMAT_DEPTH, width = render.get_window_width(), height = render.get_window_height(), u_wrap = graphics.TEXTURE_WRAP_CLAMP_TO_EDGE, v_wrap = graphics.TEXTURE_WRAP_CLAMP_TO_EDGE } self.my_render_target = render.render_target({[graphics.BUFFER_TYPE_COLOR0_BIT] = color_params, [graphics.BUFFER_TYPE_DEPTH_BIT] = depth_params }) end function update(self, dt) -- enable target so all drawing is done to it render.set_render_target(self.my_render_target) -- draw a predicate to the render target render.draw(self.my_pred) end ``` How to create a render target with multiple outputs: ``` function init(self) -- render target buffer parameters local color_params_rgba = { format = graphics.TEXTURE_FORMAT_RGBA, width = render.get_window_width(), height = render.get_window_height(), min_filter = graphics.TEXTURE_FILTER_LINEAR, mag_filter = graphics.TEXTURE_FILTER_LINEAR, u_wrap = graphics.TEXTURE_WRAP_CLAMP_TO_EDGE, v_wrap = graphics.TEXTURE_WRAP_CLAMP_TO_EDGE } local color_params_float = { format = graphics.TEXTURE_FORMAT_RG32F, width = render.get_window_width(), height = render.get_window_height(), min_filter = graphics.TEXTURE_FILTER_LINEAR, mag_filter = graphics.TEXTURE_FILTER_LINEAR, u_wrap = graphics.TEXTURE_WRAP_CLAMP_TO_EDGE, v_wrap = graphics.TEXTURE_WRAP_CLAMP_TO_EDGE } -- Create a render target with three color attachments -- Note: No depth buffer is attached here self.my_render_target = render.render_target({ [graphics.BUFFER_TYPE_COLOR0_BIT] = color_params_rgba, [graphics.BUFFER_TYPE_COLOR1_BIT] = color_params_rgba, [graphics.BUFFER_TYPE_COLOR2_BIT] = color_params_float, }) end function update(self, dt) -- enable target so all drawing is done to it render.enable_render_target(self.my_render_target) -- draw a predicate to the render target render.draw(self.my_pred) end ``` ### render.RENDER_TARGET_DEFAULT *Type:* CONSTANT ### render.set_blend_func *Type:* FUNCTION Specifies the arithmetic used when computing pixel values that are written to the frame buffer. In RGBA mode, pixels can be drawn using a function that blends the source RGBA pixel values with the destination pixel values already in the frame buffer. Blending is initially disabled. source_factor specifies which method is used to scale the source color components. destination_factor specifies which method is used to scale the destination color components. Source color components are referred to as (Rs,Gs,Bs,As). Destination color components are referred to as (Rd,Gd,Bd,Ad). The color specified by setting the blendcolor is referred to as (Rc,Gc,Bc,Ac). The source scale factor is referred to as (sR,sG,sB,sA). The destination scale factor is referred to as (dR,dG,dB,dA). The color values have integer values between 0 and (kR,kG,kB,kA), where kc = 2mc - 1 and mc is the number of bitplanes for that color. I.e for 8 bit color depth, color values are between 0 and 255. Available factor constants and corresponding scale factors: Factor constant Scale factor (fR,fG,fB,fA) graphics.BLEND_FACTOR_ZERO (0,0,0,0) graphics.BLEND_FACTOR_ONE (1,1,1,1) graphics.BLEND_FACTOR_SRC_COLOR (Rs/kR,Gs/kG,Bs/kB,As/kA) graphics.BLEND_FACTOR_ONE_MINUS_SRC_COLOR (1,1,1,1) - (Rs/kR,Gs/kG,Bs/kB,As/kA) graphics.BLEND_FACTOR_DST_COLOR (Rd/kR,Gd/kG,Bd/kB,Ad/kA) graphics.BLEND_FACTOR_ONE_MINUS_DST_COLOR (1,1,1,1) - (Rd/kR,Gd/kG,Bd/kB,Ad/kA) graphics.BLEND_FACTOR_SRC_ALPHA (As/kA,As/kA,As/kA,As/kA) graphics.BLEND_FACTOR_ONE_MINUS_SRC_ALPHA (1,1,1,1) - (As/kA,As/kA,As/kA,As/kA) graphics.BLEND_FACTOR_DST_ALPHA (Ad/kA,Ad/kA,Ad/kA,Ad/kA) graphics.BLEND_FACTOR_ONE_MINUS_DST_ALPHA (1,1,1,1) - (Ad/kA,Ad/kA,Ad/kA,Ad/kA) graphics.BLEND_FACTOR_CONSTANT_COLOR (Rc,Gc,Bc,Ac) graphics.BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR (1,1,1,1) - (Rc,Gc,Bc,Ac) graphics.BLEND_FACTOR_CONSTANT_ALPHA (Ac,Ac,Ac,Ac) graphics.BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA (1,1,1,1) - (Ac,Ac,Ac,Ac) graphics.BLEND_FACTOR_SRC_ALPHA_SATURATE (i,i,i,1) where i = min(As, kA - Ad) /kA The blended RGBA values of a pixel comes from the following equations: Rd = min(kR, Rs * sR + Rd * dR) Gd = min(kG, Gs * sG + Gd * dG) Bd = min(kB, Bs * sB + Bd * dB) Ad = min(kA, As * sA + Ad * dA) Blend function (graphics.BLEND_FACTOR_SRC_ALPHA, graphics.BLEND_FACTOR_ONE_MINUS_SRC_ALPHA) is useful for drawing with transparency when the drawn objects are sorted from farthest to nearest. It is also useful for drawing antialiased points and lines in arbitrary order. **Parameters** - `source_factor` (number) - source factor - `destination_factor` (number) - destination factor **Examples** Set the blend func to the most common one: ``` render.set_blend_func(graphics.BLEND_FACTOR_SRC_ALPHA, graphics.BLEND_FACTOR_ONE_MINUS_SRC_ALPHA) ``` ### render.set_camera *Type:* FUNCTION Sets the current render camera to be used for rendering. If a render camera has been set by the render script, the renderer will be using its projection and view matrix during rendering. If a projection and/or view matrix has been set by the render script, they will not be used until the current render camera has been reset by calling render.set_camera(). If the 'use_frustum' flag in the options table has been set to true, the renderer will automatically use the camera frustum for frustum culling regardless of what frustum is being passed into the render.draw() function. Note that the frustum plane option in render.draw can still be used together with the camera. **Parameters** - `camera` (url | number | nil) - camera id to use, or nil to reset - `options` (table) (optional) - optional table with properties:
use_frustum
boolean If true, the renderer will use the cameras view-projection matrix for frustum culling (default: false)
**Examples** Set the current camera to be used for rendering ``` render.set_camera("main:/my_go#camera") render.draw(self.my_pred) render.set_camera(nil) ``` Use the camera frustum for frustum culling together with a specific frustum plane option for the draw command ``` -- The camera frustum will take precedence over the frustum plane option in render.draw render.set_camera("main:/my_go#camera", { use_frustum = true }) -- However, we can still customize the frustum planes regardless of the camera option! render.draw(self.my_pred, { frustum_planes = render.FRUSTUM_PLANES_ALL }) render.set_camera() ``` ### render.set_color_mask *Type:* FUNCTION Specifies whether the individual color components in the frame buffer is enabled for writing (true) or disabled (false). For example, if blue is false, nothing is written to the blue component of any pixel in any of the color buffers, regardless of the drawing operation attempted. Note that writing are either enabled or disabled for entire color components, not the individual bits of a component. The component masks are all initially true. **Parameters** - `red` (boolean) - red mask - `green` (boolean) - green mask - `blue` (boolean) - blue mask - `alpha` (boolean) - alpha mask **Examples** ``` -- alpha cannot be written to frame buffer render.set_color_mask(true, true, true, false) ``` ### render.set_compute *Type:* FUNCTION The name of the compute program must be specified in the ".render" resource set in the "game.project" setting. If nil (or no arguments) are passed to this function, the current compute program will instead be disabled. **Parameters** - `compute` (string | hash | nil) - compute id to use, or nil to disable **Examples** Enable compute program named "fractals", then dispatch it. ``` render.set_compute("fractals") render.enable_texture(0, self.backing_texture) render.dispatch_compute(128, 128, 1) render.set_compute() ``` ### render.set_cull_face *Type:* FUNCTION Specifies whether front- or back-facing polygons can be culled when polygon culling is enabled. Polygon culling is initially disabled. If mode is graphics.FACE_TYPE_FRONT_AND_BACK, no polygons are drawn, but other primitives such as points and lines are drawn. The initial value for face_type is graphics.FACE_TYPE_BACK. **Parameters** - `face_type` (number) - face type
  • graphics.FACE_TYPE_FRONT
  • graphics.FACE_TYPE_BACK
  • graphics.FACE_TYPE_FRONT_AND_BACK
**Examples** How to enable polygon culling and set front face culling: ``` render.enable_state(graphics.STATE_CULL_FACE) render.set_cull_face(graphics.FACE_TYPE_FRONT) ``` ### render.set_depth_func *Type:* FUNCTION Specifies the function that should be used to compare each incoming pixel depth value with the value present in the depth buffer. The comparison is performed only if depth testing is enabled and specifies the conditions under which a pixel will be drawn. Function constants: graphics.COMPARE_FUNC_NEVER (never passes) graphics.COMPARE_FUNC_LESS (passes if the incoming depth value is less than the stored value) graphics.COMPARE_FUNC_LEQUAL (passes if the incoming depth value is less than or equal to the stored value) graphics.COMPARE_FUNC_GREATER (passes if the incoming depth value is greater than the stored value) graphics.COMPARE_FUNC_GEQUAL (passes if the incoming depth value is greater than or equal to the stored value) graphics.COMPARE_FUNC_EQUAL (passes if the incoming depth value is equal to the stored value) graphics.COMPARE_FUNC_NOTEQUAL (passes if the incoming depth value is not equal to the stored value) graphics.COMPARE_FUNC_ALWAYS (always passes) The depth function is initially set to graphics.COMPARE_FUNC_LESS. **Parameters** - `func` (number) - depth test function, see the description for available values **Examples** Enable depth test and set the depth test function to "not equal". ``` render.enable_state(graphics.STATE_DEPTH_TEST) render.set_depth_func(graphics.COMPARE_FUNC_NOTEQUAL) ``` ### render.set_depth_mask *Type:* FUNCTION Specifies whether the depth buffer is enabled for writing. The supplied mask governs if depth buffer writing is enabled (true) or disabled (false). The mask is initially true. **Parameters** - `depth` (boolean) - depth mask **Examples** How to turn off writing to the depth buffer: ``` render.set_depth_mask(false) ``` ### render.set_listener *Type:* FUNCTION Set or remove listener. Currenly only only two type of events can arrived: render.CONTEXT_EVENT_CONTEXT_LOST - when rendering context lost. Rending paused and all graphics resources become invalid. render.CONTEXT_EVENT_CONTEXT_RESTORED - when rendering context was restored. Rendering still paused and graphics resources still invalid but can be reloaded. **Parameters** - `callback` (function(self, event_type) | nil) - A callback that receives all render related events. Pass nil if want to remove listener.
self
object The render script
event_type
string Rendering event. Possible values: render.CONTEXT_EVENT_CONTEXT_LOST, render.CONTEXT_EVENT_CONTEXT_RESTORED
**Examples** Set listener and handle render context events. ``` --- custom.render_script function init(self) render.set_listener(function(self, event_type) if event_type == render.CONTEXT_EVENT_CONTEXT_LOST then --- Some stuff when rendering context is lost elseif event_type == render.CONTEXT_EVENT_CONTEXT_RESTORED then --- Start reload resources, reload game, etc. end end) end ``` ### render.set_polygon_offset *Type:* FUNCTION Sets the scale and units used to calculate depth values. If graphics.STATE_POLYGON_OFFSET_FILL is enabled, each fragment's depth value is offset from its interpolated value (depending on the depth value of the appropriate vertices). Polygon offset can be used when drawing decals, rendering hidden-line images etc. factor specifies a scale factor that is used to create a variable depth offset for each polygon. The initial value is 0. units is multiplied by an implementation-specific value to create a constant depth offset. The initial value is 0. The value of the offset is computed as factor × DZ + r × units DZ is a measurement of the depth slope of the polygon which is the change in z (depth) values divided by the change in either x or y coordinates, as you traverse a polygon. The depth values are in window coordinates, clamped to the range [0, 1]. r is the smallest value that is guaranteed to produce a resolvable difference. It's value is an implementation-specific constant. The offset is added before the depth test is performed and before the value is written into the depth buffer. **Parameters** - `factor` (number) - polygon offset factor - `units` (number) - polygon offset units **Examples** ``` render.enable_state(graphics.STATE_POLYGON_OFFSET_FILL) render.set_polygon_offset(1.0, 1.0) ``` ### render.set_projection *Type:* FUNCTION Sets the projection matrix to use when rendering. **Parameters** - `matrix` (matrix4) - projection matrix **Examples** How to set the projection to orthographic with world origo at lower left, width and height as set in project settings and depth (z) between -1 and 1: ``` render.set_projection(vmath.matrix4_orthographic(0, render.get_width(), 0, render.get_height(), -1, 1)) ``` ### render.set_render_target *Type:* FUNCTION Sets a render target. Subsequent draw operations will be to the render target until it is replaced by a subsequent call to set_render_target. This function supports render targets created by a render script, or a render target resource. **Parameters** - `render_target` (render_target) - render target to set. render.RENDER_TARGET_DEFAULT to set the default render target - `options` (table) (optional) - optional table with behaviour parameters
transient
table Transient frame buffer types are only valid while the render target is active, i.e becomes undefined when a new target is set by a subsequent call to set_render_target. Default is all non-transient. Be aware that some hardware uses a combined depth stencil buffer and when this is the case both are considered non-transient if exclusively selected! A buffer type defined that doesn't exist in the render target is silently ignored.
  • graphics.BUFFER_TYPE_COLOR0_BIT
  • graphics.BUFFER_TYPE_DEPTH_BIT
  • graphics.BUFFER_TYPE_STENCIL_BIT
**Examples** How to set a render target and draw to it and then switch back to the default render target The render target defines the depth/stencil buffers as transient, when set_render_target is called the next time the buffers may be invalidated and allow for optimisations depending on driver support ``` function update(self, dt) -- set render target so all drawing is done to it render.set_render_target(self.my_render_target, { transient = { graphics.BUFFER_TYPE_DEPTH_BIT, graphics.BUFFER_TYPE_STENCIL_BIT } } ) -- draw a predicate to the render target render.draw(self.my_pred) -- set default render target. This also invalidates the depth and stencil buffers of the current target (self.my_render_target) -- which can be an optimisation on some hardware render.set_render_target(render.RENDER_TARGET_DEFAULT) end ``` ``` function update(self, dt) -- set render target by a render target resource identifier render.set_render_target('my_rt_resource') -- draw a predicate to the render target render.draw(self.my_pred) -- reset the render target to the default backbuffer render.set_render_target(render.RENDER_TARGET_DEFAULT) end ``` ### render.set_render_target_size *Type:* FUNCTION Sets the render target size for a render target created from either a render script, or from a render target resource. **Parameters** - `render_target` (render_target) - render target to set size for - `width` (number) - new render target width - `height` (number) - new render target height **Examples** Resize render targets to the current window size: ``` render.set_render_target_size(self.my_render_target, render.get_window_width(), render.get_window_height()) render.set_render_target_size('my_rt_resource', render.get_window_width(), render.get_window_height()) ``` ### render.set_stencil_func *Type:* FUNCTION Stenciling is similar to depth-buffering as it enables and disables drawing on a per-pixel basis. First, GL drawing primitives are drawn into the stencil planes. Second, geometry and images are rendered but using the stencil planes to mask out where to draw. The stencil test discards a pixel based on the outcome of a comparison between the reference value ref and the corresponding value in the stencil buffer. func specifies the comparison function. See the table below for values. The initial value is graphics.COMPARE_FUNC_ALWAYS. ref specifies the reference value for the stencil test. The value is clamped to the range [0, 2n-1], where n is the number of bitplanes in the stencil buffer. The initial value is 0. mask is ANDed with both the reference value and the stored stencil value when the test is done. The initial value is all 1's. Function constant: graphics.COMPARE_FUNC_NEVER (never passes) graphics.COMPARE_FUNC_LESS (passes if (ref & mask) graphics.COMPARE_FUNC_LEQUAL (passes if (ref & mask) graphics.COMPARE_FUNC_GREATER (passes if (ref & mask) > (stencil & mask)) graphics.COMPARE_FUNC_GEQUAL (passes if (ref & mask) >= (stencil & mask)) graphics.COMPARE_FUNC_EQUAL (passes if (ref & mask) = (stencil & mask)) graphics.COMPARE_FUNC_NOTEQUAL (passes if (ref & mask) != (stencil & mask)) graphics.COMPARE_FUNC_ALWAYS (always passes) **Parameters** - `func` (number) - stencil test function, see the description for available values - `ref` (number) - reference value for the stencil test - `mask` (number) - mask that is ANDed with both the reference value and the stored stencil value when the test is done **Examples** ``` -- let only 0's pass the stencil test render.set_stencil_func(graphics.COMPARE_FUNC_EQUAL, 0, 1) ``` ### render.set_stencil_mask *Type:* FUNCTION The stencil mask controls the writing of individual bits in the stencil buffer. The least significant n bits of the parameter mask, where n is the number of bits in the stencil buffer, specify the mask. Where a 1 bit appears in the mask, the corresponding bit in the stencil buffer can be written. Where a 0 bit appears in the mask, the corresponding bit in the stencil buffer is never written. The mask is initially all 1's. **Parameters** - `mask` (number) - stencil mask **Examples** ``` -- set the stencil mask to all 1:s render.set_stencil_mask(0xff) ``` ### render.set_stencil_op *Type:* FUNCTION The stencil test discards a pixel based on the outcome of a comparison between the reference value ref and the corresponding value in the stencil buffer. To control the test, call render.set_stencil_func. This function takes three arguments that control what happens to the stored stencil value while stenciling is enabled. If the stencil test fails, no change is made to the pixel's color or depth buffers, and sfail specifies what happens to the stencil buffer contents. Operator constants: graphics.STENCIL_OP_KEEP (keeps the current value) graphics.STENCIL_OP_ZERO (sets the stencil buffer value to 0) graphics.STENCIL_OP_REPLACE (sets the stencil buffer value to ref, as specified by render.set_stencil_func) graphics.STENCIL_OP_INCR (increments the stencil buffer value and clamp to the maximum representable unsigned value) graphics.STENCIL_OP_INCR_WRAP (increments the stencil buffer value and wrap to zero when incrementing the maximum representable unsigned value) graphics.STENCIL_OP_DECR (decrements the current stencil buffer value and clamp to 0) graphics.STENCIL_OP_DECR_WRAP (decrements the current stencil buffer value and wrap to the maximum representable unsigned value when decrementing zero) graphics.STENCIL_OP_INVERT (bitwise inverts the current stencil buffer value) dppass and dpfail specify the stencil buffer actions depending on whether subsequent depth buffer tests succeed (dppass) or fail (dpfail). The initial value for all operators is graphics.STENCIL_OP_KEEP. **Parameters** - `sfail` (number) - action to take when the stencil test fails - `dpfail` (number) - the stencil action when the stencil test passes - `dppass` (number) - the stencil action when both the stencil test and the depth test pass, or when the stencil test passes and either there is no depth buffer or depth testing is not enabled **Examples** Set the stencil function to never pass and operator to always draw 1's on test fail. ``` render.set_stencil_func(graphics.COMPARE_FUNC_NEVER, 1, 0xFF) -- always draw 1's on test fail render.set_stencil_op(graphics.STENCIL_OP_REPLACE, graphics.STENCIL_OP_KEEP, graphics.STENCIL_OP_KEEP) ``` ### render.set_view *Type:* FUNCTION Sets the view matrix to use when rendering. **Parameters** - `matrix` (matrix4) - view matrix to set **Examples** How to set the view and projection matrices according to the values supplied by a camera. ``` function init(self) self.view = vmath.matrix4() self.projection = vmath.matrix4() end function update(self, dt) -- set the view to the stored view value render.set_view(self.view) -- now we can draw with this view end function on_message(self, message_id, message) if message_id == hash("set_view_projection") then -- camera view and projection arrives here. self.view = message.view self.projection = message.projection end end ``` ### render.set_viewport *Type:* FUNCTION Set the render viewport to the specified rectangle. **Parameters** - `x` (number) - left corner - `y` (number) - bottom corner - `width` (number) - viewport width - `height` (number) - viewport height **Examples** ``` -- Set the viewport to the window dimensions. render.set_viewport(0, 0, render.get_window_width(), render.get_window_height()) ``` ### render.SORT_BACK_TO_FRONT *Type:* CONSTANT Depth sort far-to-near (default; good for transparent passes). ### render.SORT_FRONT_TO_BACK *Type:* CONSTANT Depth sort near-to-far (good for opaque passes to reduce overdraw). ### render.SORT_NONE *Type:* CONSTANT No per-call sorting; draw entries in insertion order. ### render_target *Type:* TYPEDEF Render target **Parameters** - `value` (number) ### resize *Type:* MESSAGE Set the size of the game window. Only works on desktop platforms. **Parameters** - `height` (number) - the new window height - `width` (number) - the new window width **Examples** ``` msg.post("@render:", "resize", { width = 1024, height = 768 } ) ``` ### texture *Type:* TYPEDEF Texture handle **Parameters** - `value` (number) ### window_resized *Type:* MESSAGE Reports a change in window size. This is initiated on window resize on desktop or by orientation changes on mobile devices. **Parameters** - `height` (number) - the new window height - `width` (number) - the new window width **Examples** ``` function on_message(self, message_id, message) -- check for the message if message_id == hash("window_resized") then -- the window was resized. end end ``` # Resource {#apis:resource-lua} **Namespace:** `resource` **Language:** Lua **Type:** Defold Lua **File:** `script_resource.cpp` **Source:** `engine/gamesys/src/gamesys/scripts/script_resource.cpp` Functions and constants to access resources. ## API ### resource.atlas *Type:* FUNCTION Constructor-like function with two purposes: Load the specified resource as part of loading the script Return a hash to the run-time version of the resource This function can only be called within go.property function calls. **Parameters** - `path` (string) (optional) - optional resource path string to the resource **Returns** - `path` (hash) - a path hash to the binary version of the resource **Examples** Load an atlas and set it to a sprite: ``` go.property("my_atlas", resource.atlas("/atlas.atlas")) function init(self) go.set("#sprite", "image", self.my_atlas) end ``` Load an atlas and set it to a gui: ``` go.property("my_atlas", resource.atlas("/atlas.atlas")) function init(self) go.set("#gui", "textures", self.my_atlas, {key = "my_atlas"}) end ``` ### resource.buffer *Type:* FUNCTION Constructor-like function with two purposes: Load the specified resource as part of loading the script Return a hash to the run-time version of the resource This function can only be called within go.property function calls. **Parameters** - `path` (string) (optional) - optional resource path string to the resource **Returns** - `path` (hash) - a path hash to the binary version of the resource **Examples** Set a unique buffer it to a sprite: ``` go.property("my_buffer", resource.buffer("/cube.buffer")) function init(self) go.set("#mesh", "vertices", self.my_buffer) end ``` ### resource.create_atlas *Type:* FUNCTION This function creates a new atlas resource that can be used in the same way as any atlas created during build time. The path used for creating the atlas must be unique, trying to create a resource at a path that is already registered will trigger an error. If the intention is to instead modify an existing atlas, use the resource.set_atlas function. Also note that the path to the new atlas resource must have a '.texturesetc' extension, meaning "/path/my_atlas" is not a valid path but "/path/my_atlas.texturesetc" is. When creating the atlas, at least one geometry and one animation is required, and an error will be raised if these requirements are not met. A reference to the resource will be held by the collection that created the resource and will automatically be released when that collection is destroyed. Note that releasing a resource essentially means decreasing the reference count of that resource, and not necessarily that it will be deleted. **Notes** - The index values are zero based where zero refers to the first entry of the vertex and uv lists **Parameters** - `path` (string) - The path to the resource. - `table` (table) - A table containing info about how to create the atlas. Supported entries:
  • texture
    string | hash the path to the texture resource, e.g "/main/my_texture.texturec"
  • animations
    table a list of the animations in the atlas. Supports the following fields:
  • id
    string the id of the animation, used in e.g sprite.play_animation
  • width
    number the width of the animation
  • height
    number the height of the animation
  • frame_start
    number index to the first geometry of the animation. Indices are lua based and must be in the range of 1 .. in atlas.
  • frame_end
    number index to the last geometry of the animation (non-inclusive). Indices are lua based and must be in the range of 1 .. in atlas.
  • playback
    constant optional playback mode of the animation, the default value is go.PLAYBACK_ONCE_FORWARD
  • fps
    number optional fps of the animation, the default value is 30
  • flip_vertical
    boolean optional flip the animation vertically, the default value is false
  • flip_horizontal
    boolean optional flip the animation horizontally, the default value is false
  • geometries
    table A list of the geometries that should map to the texture data. Supports the following fields:
  • id
    string The name of the geometry. Used when matching animations between multiple atlases
  • width
    number The width of the image the sprite geometry represents
  • height
    number The height of the image the sprite geometry represents
  • pivot_x
    number The pivot x value of the image in unit coords. (0,0) is upper left corner, (1,1) is bottom right. Default is 0.5.
  • pivot_y
    number The pivot y value of the image in unit coords. (0,0) is upper left corner, (1,1) is bottom right. Default is 0.5.
  • rotated
    boolean Whether the image is rotated 90 degrees counter-clockwise in the atlas. This affects UV coordinate generation for proper rendering. Default is false.
  • vertices
    table a list of the vertices in image space of the geometry in the form {px0, py0, px1, py1, ..., pxn, pyn}
  • uvs
    table a list of the uv coordinates in image space of the geometry in the form of {u0, v0, u1, v1, ..., un, vn}.
  • indices
    table a list of the indices of the geometry in the form {i0, i1, i2, ..., in}. Each tripe in the list represents a triangle.
**Returns** - `path` (hash) - Returns the atlas resource path **Examples** Create a backing texture and an atlas ``` function init(self) -- create an empty texture local tparams = { width = 128, height = 128, type = graphics.TEXTURE_TYPE_2D, format = graphics.TEXTURE_FORMAT_RGBA, } local my_texture_id = resource.create_texture("/my_texture.texturec", tparams) -- optionally use resource.set_texture to upload data to texture -- create an atlas with one animation and one square geometry -- note that the function doesn't support hashes for the texture, -- you need to use a string for the texture path here aswell local aparams = { texture = "/my_texture.texturec", animations = { { id = "my_animation", width = 128, height = 128, frames = { 1 } } }, geometries = { { id = 'idle0', width = 128, height = 128, pivot_x = 0.5, pivot_y = 0.5, vertices = { 0, 0, 0, 128, 128, 128, 128, 0 }, uvs = { 0, 0, 0, 128, 128, 128, 128, 0 }, indices = {0,1,2,0,2,3} } } } local my_atlas_id = resource.create_atlas("/my_atlas.texturesetc", aparams) -- assign the atlas to the 'sprite' component on the same go go.set("#sprite", "image", my_atlas_id) end ``` ### resource.create_buffer *Type:* FUNCTION This function creates a new buffer resource that can be used in the same way as any buffer created during build time. The function requires a valid buffer created from either buffer.create or another pre-existing buffer resource. By default, the new resource will take ownership of the buffer lua reference, meaning the buffer will not automatically be removed when the lua reference to the buffer is garbage collected. This behaviour can be overruled by specifying 'transfer_ownership = false' in the argument table. If the new buffer resource is created from a buffer object that is created by another resource, the buffer object will be copied and the new resource will effectively own a copy of the buffer instead. Note that the path to the new resource must have the '.bufferc' extension, "/path/my_buffer" is not a valid path but "/path/my_buffer.bufferc" is. The path must also be unique, attempting to create a buffer with the same name as an existing resource will raise an error. **Parameters** - `path` (string) - The path to the resource. - `table` (table) (optional) - A table containing info about how to create the buffer. Supported entries:
  • buffer
    buffer the buffer to bind to this resource
  • transfer_ownership
    boolean optional flag to determine wether or not the resource should take over ownership of the buffer object (default true)
**Returns** - `path` (hash) - Returns the buffer resource path **Examples** Create a buffer object and bind it to a buffer resource ``` function init(self) local size = 1 local positions = { -- triangle 1 size, size, 0, -size, -size, 0, size, -size, 0, -- triangle 2 size, size, 0, -size, size, 0, -size, -size, 0, } local buffer_handle = buffer.create(#positions, { { name = hash("position"), type = buffer.VALUE_TYPE_FLOAT32, count = 3 } }) local stream = buffer.get_stream(buffer_handle, hash("position")) -- transfer vertex data to buffer for k=1,#positions do stream[k] = positions[k] end local my_buffer = resource.create_buffer("/my_buffer.bufferc", { buffer = buffer_handle }) go.set("/go#mesh", "vertices", my_buffer) end ```Create a buffer resource from existing resource ```lua function init(self) local res = resource.get_buffer("/my_buffer_path.bufferc") -- create a cloned buffer resource from another resource buffer local buf = reource.create_buffer("/my_cloned_buffer.bufferc", { buffer = res }) -- assign cloned buffer to a mesh component go.set("/go#mesh", "vertices", buf) end ``` ### resource.create_sound_data *Type:* FUNCTION Creates a sound data resource Supported formats are .oggc, .opusc and .wavc **Parameters** - `path` (string) - the path to the resource. Must not already exist. - `options` (table) (optional) - A table containing parameters for the text. Supported entries:
data
string The raw data of the file. May be partial, but must include the header of the file
filesize
number If the file is partial, it must also specify the full size of the complete file.
partial
boolean Is the data not representing the full file, but just the initial chunk?
**Returns** - `path_hash` (hash) - the resulting path hash to the resource **Examples** ``` function init(self) -- create a new sound resource, given the initial chunk of the file local relative_path = "/a/unique/resource/name.oggc" local hash = resource.create_sound_data(relative_path, { data = data, filesize = filesize, partial = true }) go.set("#music", "sound", hash) -- override the previous sound resource sound.play("#music") -- start the playing end ``` ### resource.create_texture *Type:* FUNCTION Creates a new texture resource that can be used in the same way as any texture created during build time. The path used for creating the texture must be unique, trying to create a resource at a path that is already registered will trigger an error. If the intention is to instead modify an existing texture, use the resource.set_texture function. Also note that the path to the new texture resource must have a '.texturec' extension, meaning "/path/my_texture" is not a valid path but "/path/my_texture.texturec" is. If the texture is created without a buffer, the pixel data will be blank. **Parameters** - `path` (string) - The path to the resource. - `table` (table) - A table containing info about how to create the texture. Supported entries:
type
number The texture type. Supported values:
  • graphics.TEXTURE_TYPE_2D
  • graphics.TEXTURE_TYPE_IMAGE_2D
  • graphics.TEXTURE_TYPE_3D
  • graphics.TEXTURE_TYPE_IMAGE_3D
  • graphics.TEXTURE_TYPE_CUBE_MAP
width
number The width of the texture (in pixels). Must be larger than 0.
height
number The width of the texture (in pixels). Must be larger than 0.
depth
number The depth of the texture (in pixels). Must be larger than 0. Only used when type is graphics.TEXTURE_TYPE_3D or graphics.TEXTURE_TYPE_IMAGE_3D.
format
number The texture format, note that some of these formats might not be supported by the running device. Supported values:
  • graphics.TEXTURE_FORMAT_LUMINANCE
  • graphics.TEXTURE_FORMAT_RGB
  • graphics.TEXTURE_FORMAT_RGBA
These constants might not be available on the device:
  • graphics.TEXTURE_FORMAT_RGB_PVRTC_2BPPV1
  • graphics.TEXTURE_FORMAT_RGB_PVRTC_4BPPV1
  • graphics.TEXTURE_FORMAT_RGBA_PVRTC_2BPPV1
  • graphics.TEXTURE_FORMAT_RGBA_PVRTC_4BPPV1
  • graphics.TEXTURE_FORMAT_RGB_ETC1
  • graphics.TEXTURE_FORMAT_RGBA_ETC2
  • graphics.TEXTURE_FORMAT_RGBA_ASTC_4X4
  • graphics.TEXTURE_FORMAT_RGB_BC1
  • graphics.TEXTURE_FORMAT_RGBA_BC3
  • graphics.TEXTURE_FORMAT_R_BC4
  • graphics.TEXTURE_FORMAT_RG_BC5
  • graphics.TEXTURE_FORMAT_RGBA_BC7
  • graphics.TEXTURE_FORMAT_RGB16F
  • graphics.TEXTURE_FORMAT_RGB32F
  • graphics.TEXTURE_FORMAT_RGBA16F
  • graphics.TEXTURE_FORMAT_RGBA32F
  • graphics.TEXTURE_FORMAT_R16F
  • graphics.TEXTURE_FORMAT_RG16F
  • graphics.TEXTURE_FORMAT_R32F
  • graphics.TEXTURE_FORMAT_RG32F
You can test if the device supports these values by checking if a specific enum is nil or not:
if graphics.TEXTURE_FORMAT_RGBA16F ~= nil then
    -- it is safe to use this format
end
flags
number Texture creation flags that can be used to dictate how the texture is created. The default value is graphics.TEXTURE_USAGE_FLAG_SAMPLE, which means that the texture can be sampled from a shader. These flags may or may not be supported on the running device and/or the underlying graphics API and is simply used internally as a 'hint' when creating the texture. There is no guarantee that any of these will have any effect. Supported values:
  • graphics.TEXTURE_USAGE_FLAG_SAMPLE - The texture can be sampled from a shader (default)
  • graphics.TEXTURE_USAGE_FLAG_MEMORYLESS - The texture can be used as a memoryless texture, i.e only transient memory for the texture is used during rendering
  • graphics.TEXTURE_USAGE_FLAG_STORAGE - The texture can be used as a storage texture, which is required for a shader to write to the texture
max_mipmaps
number optional max number of mipmaps. Defaults to zero, i.e no mipmap support
compression_type
number optional specify the compression type for the data in the buffer object that holds the texture data. Will only be used when a compressed buffer has been passed into the function. Creating an empty texture with no buffer data is not supported as a core feature. Defaults to graphics.COMPRESSION_TYPE_DEFAULT, i.e no compression. Supported values:
  • COMPRESSION_TYPE_DEFAULT
  • COMPRESSION_TYPE_BASIS_UASTC
- `buffer` (buffer) - optional buffer of precreated pixel data **Returns** - `path` (hash) - The path to the resource. 3D Textures are currently only supported on OpenGL and Vulkan adapters. To check if your device supports 3D textures, use: ```lua if graphics.TEXTURE_TYPE_3D ~= nil then -- Device and graphics adapter support 3D textures end **Examples** How to create an 128x128 RGBA texture resource and assign it to a model ``` function init(self) local tparams = { width = 128, height = 128, type = graphics.TEXTURE_TYPE_2D, format = graphics.TEXTURE_FORMAT_RGBA, } local my_texture_id = resource.create_texture("/my_custom_texture.texturec", tparams) go.set("#model", "texture0", my_texture_id) end ```How to create an 128x128 floating point texture (RGBA32F) resource from a buffer object ```lua function init(self) -- Create a new buffer with 4 components and FLOAT32 type local tbuffer = buffer.create(128 * 128, { {name=hash("rgba"), type=buffer.VALUE_TYPE_FLOAT32, count=4} } ) local tstream = buffer.get_stream(tbuffer, hash("rgba")) -- Fill the buffer stream with some float values for y=1,128 do for x=1,128 do local index = (y-1) * 128 * 4 + (x-1) * 4 + 1 tstream[index + 0] = 999.0 tstream[index + 1] = -1.0 tstream[index + 2] = 0.5 tstream[index + 3] = 1.0 end end -- Create a 2D Texture with a RGBA23F format local tparams = { width = 128, height = 128, type = graphics.TEXTURE_TYPE_2D, format = graphics.TEXTURE_FORMAT_RGBA32F, } -- Note that we pass the buffer as the last argument here! local my_texture_id = resource.create_texture("/my_custom_texture.texturec", tparams, tbuffer) -- assign the texture to a model go.set("#model", "texture0", my_texture_id) end ```How to create a 32x32x32 floating point 3D texture that can be used to generate volumetric data in a compute shader ```lua function init(self) local t_volume = resource.create_texture("/my_backing_texture.texturec", { type = graphics.TEXTURE_TYPE_IMAGE_3D, width = 32, height = 32, depth = 32, format = resource.TEXTURE_FORMAT_RGBA32F, flags = resource.TEXTURE_USAGE_FLAG_STORAGE + resource.TEXTURE_USAGE_FLAG_SAMPLE, }) -- pass the backing texture to the render script msg.post("@render:", "add_textures", { t_volume }) end ```How to create 512x512 texture array with 5 pages. ```lua local new_tex = resource.create_texture("/runtime/example_array.texturec", { type = graphics.TEXTURE_TYPE_2D_ARRAY, width = 512, height = 512, page_count = 5, format = graphics.TEXTURE_FORMAT_RGB, }) ``` ### resource.create_texture_async *Type:* FUNCTION Creates a new texture resource that can be used in the same way as any texture created during build time. The path used for creating the texture must be unique, trying to create a resource at a path that is already registered will trigger an error. If the intention is to instead modify an existing texture, use the resource.set_texture function. Also note that the path to the new texture resource must have a '.texturec' extension, meaning "/path/my_texture" is not a valid path but "/path/my_texture.texturec" is. If the texture is created without a buffer, the pixel data will be blank. The difference between the async version and resource.create_texture is that the texture data will be uploaded in a graphics worker thread. The function will return a resource immediately that contains a 1x1 blank texture which can be used immediately after the function call. When the new texture has been uploaded, the initial blank texture will be deleted and replaced with the new texture. Be careful when using the initial texture handle handle as it will not be valid after the upload has finished. **Parameters** - `path` (string | hash) - The path to the resource. - `table` (table) -
A table containing info about how to create the texture. Supported entries:
type
number The texture type. Supported values:
  • graphics.TEXTURE_TYPE_2D
  • graphics.TEXTURE_TYPE_IMAGE_2D
  • graphics.TEXTURE_TYPE_3D
  • graphics.TEXTURE_TYPE_IMAGE_3D
  • graphics.TEXTURE_TYPE_CUBE_MAP
width
number The width of the texture (in pixels). Must be larger than 0.
height
number The width of the texture (in pixels). Must be larger than 0.
depth
number The depth of the texture (in pixels). Must be larger than 0. Only used when type is graphics.TEXTURE_TYPE_3D or graphics.TEXTURE_TYPE_IMAGE_3D.
format
number The texture format, note that some of these formats might not be supported by the running device. Supported values:
  • graphics.TEXTURE_FORMAT_LUMINANCE
  • graphics.TEXTURE_FORMAT_RGB
  • graphics.TEXTURE_FORMAT_RGBA
These constants might not be available on the device:
  • graphics.TEXTURE_FORMAT_RGB_PVRTC_2BPPV1
  • graphics.TEXTURE_FORMAT_RGB_PVRTC_4BPPV1
  • graphics.TEXTURE_FORMAT_RGBA_PVRTC_2BPPV1
  • graphics.TEXTURE_FORMAT_RGBA_PVRTC_4BPPV1
  • graphics.TEXTURE_FORMAT_RGB_ETC1
  • graphics.TEXTURE_FORMAT_RGBA_ETC2
  • graphics.TEXTURE_FORMAT_RGBA_ASTC_4X4
  • graphics.TEXTURE_FORMAT_RGB_BC1
  • graphics.TEXTURE_FORMAT_RGBA_BC3
  • graphics.TEXTURE_FORMAT_R_BC4
  • graphics.TEXTURE_FORMAT_RG_BC5
  • graphics.TEXTURE_FORMAT_RGBA_BC7
  • graphics.TEXTURE_FORMAT_RGB16F
  • graphics.TEXTURE_FORMAT_RGB32F
  • graphics.TEXTURE_FORMAT_RGBA16F
  • graphics.TEXTURE_FORMAT_RGBA32F
  • graphics.TEXTURE_FORMAT_R16F
  • graphics.TEXTURE_FORMAT_RG16F
  • graphics.TEXTURE_FORMAT_R32F
  • graphics.TEXTURE_FORMAT_RG32F
You can test if the device supports these values by checking if a specific enum is nil or not:
if graphics.TEXTURE_FORMAT_RGBA16F ~= nil then
    -- it is safe to use this format
end
flags
number Texture creation flags that can be used to dictate how the texture is created. Supported values:
  • graphics.TEXTURE_USAGE_FLAG_SAMPLE - The texture can be sampled from a shader (default)
  • graphics.TEXTURE_USAGE_FLAG_MEMORYLESS - The texture can be used as a memoryless texture, i.e only transient memory for the texture is used during rendering
  • graphics.TEXTURE_USAGE_FLAG_STORAGE - The texture can be used as a storage texture, which is required for a shader to write to the texture
max_mipmaps
number optional max number of mipmaps. Defaults to zero, i.e no mipmap support
compression_type
number optional specify the compression type for the data in the buffer object that holds the texture data. Will only be used when a compressed buffer has been passed into the function. Creating an empty texture with no buffer data is not supported as a core feature. Defaults to graphics.COMPRESSION_TYPE_DEFAULT, i.e no compression. Supported values:
  • COMPRESSION_TYPE_DEFAULT
  • COMPRESSION_TYPE_BASIS_UASTC
- `buffer` (buffer) - optional buffer of precreated pixel data - `callback` (function) - callback function when texture is created (self, request_id, resource) **Returns** - `path` (hash) - The path to the texture resource. - `request_id` (number) - The request id for the async request. 3D Textures are currently only supported on OpenGL and Vulkan adapters. To check if your device supports 3D textures, use: ```lua if graphics.TEXTURE_TYPE_3D ~= nil then -- Device and graphics adapter support 3D textures end **Examples** Create a texture resource asyncronously with a buffer and a callback ``` function callback(self, request_id, resource) -- The resource has been updated with a new texture, -- so we can update other systems with the new handle, -- or update components to use the resource if we want local tinfo = resource.get_texture_info(resource) msg.post("@render:", "set_backing_texture", tinfo.handle) end function init(self) -- Create a texture resource async local tparams = { width = 128, height = 128, type = graphics.TEXTURE_TYPE_2D, format = graphics.TEXTURE_FORMAT_RGBA, } -- Create a new buffer with 4 components local tbuffer = buffer.create(tparams.width * tparams.height, { {name=hash("rgba"), type=buffer.VALUE_TYPE_UINT8, count=4} } ) local tstream = buffer.get_stream(tbuffer, hash("rgba")) -- Fill the buffer stream with some float values for y=1,tparams.width do for x=1,tparams.height do local index = (y-1) * 128 * 4 + (x-1) * 4 + 1 tstream[index + 0] = 255 tstream[index + 1] = 0 tstream[index + 2] = 255 tstream[index + 3] = 255 end end -- create the texture local tpath, request_id = resource.create_texture_async("/my_texture.texturec", tparams, tbuffer, callback) -- at this point you can use the resource as-is, but note that the texture will be a blank 1x1 texture -- that will be removed once the new texture has been updated go.set("#model", "texture0", tpath) end ```Create a texture resource asyncronously without a callback ```lua function init(self) -- Create a texture resource async local tparams = { width = 128, height = 128, type = graphics.TEXTURE_TYPE_2D, format = graphics.TEXTURE_FORMAT_RGBA, } -- Create a new buffer with 4 components local tbuffer = buffer.create(tparams.width * tparams.height, { {name=hash("rgba"), type=buffer.VALUE_TYPE_UINT8, count=4} } ) local tstream = buffer.get_stream(tbuffer, hash("rgba")) -- Fill the buffer stream with some float values for y=1,tparams.width do for x=1,tparams.height do local index = (y-1) * 128 * 4 + (x-1) * 4 + 1 tstream[index + 0] = 255 tstream[index + 1] = 0 tstream[index + 2] = 255 tstream[index + 3] = 255 end end -- create the texture local tpath, request_id = resource.create_texture_async("/my_texture.texturec", tparams, tbuffer) -- at this point you can use the resource as-is, but note that the texture will be a blank 1x1 texture -- that will be removed once the new texture has been updated go.set("#model", "texture0", tpath) end ``` ### resource.font *Type:* FUNCTION Constructor-like function with two purposes: Load the specified resource as part of loading the script Return a hash to the run-time version of the resource This function can only be called within go.property function calls. **Parameters** - `path` (string) (optional) - optional resource path string to the resource **Returns** - `path` (hash) - a path hash to the binary version of the resource **Examples** Load a font and set it to a label: ``` go.property("my_font", resource.font("/font.font")) function init(self) go.set("#label", "font", self.my_font) end ``` Load a font and set it to a gui: ``` go.property("my_font", resource.font("/font.font")) function init(self) go.set("#gui", "fonts", self.my_font, {key = "my_font"}) end ``` ### resource.get_atlas *Type:* FUNCTION Returns the atlas data for an atlas **Parameters** - `path` (hash | string) - The path to the atlas resource **Returns** - `data` (table) - A table with the following entries:
  • texture
  • geometries
  • animations
Each animation entry also contains a frames table with indices into geometries, preserving the frame-to-geometry mapping used by the atlas. See resource.set_atlas for a detailed description of each field ### resource.get_buffer *Type:* FUNCTION gets the buffer from a resource **Parameters** - `path` (hash | string) - The path to the resource **Returns** - `buffer` (buffer) - The resource buffer **Examples** How to get the data from a buffer ``` function init(self) local res_path = go.get("#mesh", "vertices") local buf = resource.get_buffer(res_path) local stream_positions = buffer.get_stream(buf, "position") for i=1,#stream_positions do print(i, stream_positions[i]) end end ``` ### resource.get_render_target_info *Type:* FUNCTION Gets render target info from a render target resource path or a render target handle **Parameters** - `path` (hash | string | number) - The path to the resource or a render target handle **Returns** - `table` (table) - A table containing info about the render target:
handle
number the opaque handle to the texture resource
'attachments'
table a table of attachments, where each attachment contains the following entries:
width
number width of the texture
height
number height of the texture
depth
number depth of the texture (i.e 1 for a 2D texture and 6 for a cube map)
mipmaps
number number of mipmaps of the texture
type
number The texture type. Supported values:
  • graphics.TEXTURE_TYPE_2D
  • graphics.TEXTURE_TYPE_CUBE_MAP
  • graphics.TEXTURE_TYPE_2D_ARRAY
buffer_type
number The attachment buffer type. Supported values:
  • resource.BUFFER_TYPE_COLOR0
  • resource.BUFFER_TYPE_COLOR1
  • resource.BUFFER_TYPE_COLOR2
  • resource.BUFFER_TYPE_COLOR3
  • resource.BUFFER_TYPE_DEPTH
  • resource.BUFFER_TYPE_STENCIL
  • texture
    hash The hashed path to the attachment texture resource. This field is only available if the render target passed in is a resource.
**Examples** Get the metadata from a render target resource ``` function init(self) local info = resource.get_render_target_info("/my_render_target.render_targetc") -- the info table contains meta data about all the render target attachments -- so it's not necessary to use resource.get_texture here, but we do it here -- just to show that it's possible: local info_attachment_1 = resource.get_texture_info(info.attachments[1].handle) end ```Get a texture attachment from a render target and set it on a model component ```lua function init(self) local info = resource.get_render_target_info("/my_render_target.render_targetc") local attachment = info.attachments[1].texture -- you can also get texture info from the 'texture' field, since it's a resource hash local texture_info = resource.get_texture_info(attachment) go.set("#model", "texture0", attachment) end ``` ### resource.get_text_metrics *Type:* FUNCTION Gets the text metrics from a font **Parameters** - `url` (hash) - the font to get the (unscaled) metrics from - `text` (string) - text to measure - `options` (table) (optional) - A table containing parameters for the text. Supported entries:
width
number The width of the text field. Not used if line_break is false.
leading
number The leading (default 1.0)
tracking
number The tracking (default 0.0)
line_break
boolean If the calculation should consider line breaks (default false)
**Returns** - `metrics` (table) - a table with the following fields:
  • width
  • height
  • max_ascent
  • max_descent
**Examples** ``` function init(self) local font = go.get("#label", "font") local metrics = resource.get_text_metrics(font, "The quick brown fox\n jumps over the lazy dog") pprint(metrics) end ``` ### resource.get_texture_info *Type:* FUNCTION Gets texture info from a texture resource path or a texture handle **Parameters** - `path` (hash | string | number) - The path to the resource or a texture handle **Returns** - `table` (table) - A table containing info about the texture:
handle
number the opaque handle to the texture resource
width
number width of the texture
height
number height of the texture
depth
number depth of the texture (i.e 1 for a 2D texture, 6 for a cube map, the actual depth of a 3D texture)
page_count
number number of pages of the texture array. For 2D texture value is 1. For cube map - 6
mipmaps
number number of mipmaps of the texture
flags
number usage hints of the texture.
type
number The texture type. Supported values:
  • graphics.TEXTURE_TYPE_2D
  • graphics.TEXTURE_TYPE_2D_ARRAY
  • graphics.TEXTURE_TYPE_IMAGE_2D
  • graphics.TEXTURE_TYPE_3D
  • graphics.TEXTURE_TYPE_IMAGE_3D
  • graphics.TEXTURE_TYPE_CUBE_MAP
**Examples** Create a new texture and get the metadata from it ``` function init(self) -- create an empty texture local tparams = { width = 128, height = 128, type = graphics.TEXTURE_TYPE_2D, format = graphics.TEXTURE_FORMAT_RGBA, } local my_texture_path = resource.create_texture("/my_texture.texturec", tparams) local my_texture_info = resource.get_texture_info(my_texture_path) -- my_texture_info now contains -- { -- handle = , -- width = 128, -- height = 128, -- depth = 1 -- mipmaps = 1, -- page_count = 1, -- type = graphics.TEXTURE_TYPE_2D, -- flags = graphics.TEXTURE_USAGE_FLAG_SAMPLE -- } end ```Get the meta data from an atlas resource ```lua function init(self) local my_atlas_info = resource.get_atlas("/my_atlas.a.texturesetc") local my_texture_info = resource.get_texture_info(my_atlas_info.texture) -- my_texture_info now contains the information about the texture that is backing the atlas end ``` ### resource.load *Type:* FUNCTION Loads the resource data for a specific resource. **Parameters** - `path` (string) - The path to the resource **Returns** - `buffer` (buffer) - Returns the buffer stored on disc **Examples** ``` -- read custom resource data into buffer local buffer = resource.load("/resources/datafile") ``` In order for the engine to include custom resources in the build process, you need to specify them in the "game.project" settings file: ``` [project] title = My project version = 0.1 custom_resources = resources/,assets/level_data.json ``` ### resource.material *Type:* FUNCTION Constructor-like function with two purposes: Load the specified resource as part of loading the script Return a hash to the run-time version of the resource This function can only be called within go.property function calls. **Parameters** - `path` (string) (optional) - optional resource path string to the resource **Returns** - `path` (hash) - a path hash to the binary version of the resource **Examples** Load a material and set it to a sprite: ``` go.property("my_material", resource.material("/material.material")) function init(self) go.set("#sprite", "material", self.my_material) end ``` Load a material resource and update a named material with the resource: ``` go.property("my_material", resource.material("/material.material")) function init(self) go.set("#gui", "materials", self.my_material, {key = "my_material"}) end ``` ### resource.release *Type:* FUNCTION Release a resource. This is a potentially dangerous operation, releasing resources currently being used can cause unexpected behaviour. **Parameters** - `path` (hash | string) - The path to the resource. ### resource.render_target *Type:* FUNCTION Constructor-like function with two purposes: Load the specified resource as part of loading the script Return a hash to the run-time version of the resource This function can only be called within go.property function calls. **Parameters** - `path` (string) (optional) - optional resource path string to the resource **Returns** - `path` (hash) - a path hash to the binary version of the resource **Examples** Set a render target color attachment as a model texture: ``` go.property("my_render_target", resource.render_target("/rt.render_target")) function init(self) local rt_info = resource.get_render_target_info(self.my_render_target) go.set("#model", "texture0", rt_info.attachments[1].texture) end ``` ### resource.set *Type:* FUNCTION Sets the resource data for a specific resource **Parameters** - `path` (string | hash) - The path to the resource - `buffer` (buffer) - The buffer of precreated data, suitable for the intended resource type **Examples** Assuming the folder "/res" is added to the project custom resources: ``` -- load a texture resource and set it on a sprite local buffer = resource.load("/res/new.texturec") resource.set(go.get("#sprite", "texture0"), buffer) ``` ### resource.set_atlas *Type:* FUNCTION Sets the data for a specific atlas resource. Setting new atlas data is specified by passing in a texture path for the backing texture of the atlas, a list of geometries and a list of animations that map to the entries in the geometry list. The geometry entries are represented by three lists: vertices, uvs and indices that together represent triangles that are used in other parts of the engine to produce render objects from. Vertex and uv coordinates for the geometries are expected to be in pixel coordinates where 0,0 is the top left corner of the texture. There is no automatic padding or margin support when setting custom data, which could potentially cause filtering artifacts if used with a material sampler that has linear filtering. If that is an issue, you need to calculate padding and margins manually before passing in the geometry data to this function. **Notes** - Custom atlas data is not compatible with slice-9 for sprites - The index values are zero based where zero refers to the first entry of the vertex and uv lists **Parameters** - `path` (hash | string) - The path to the atlas resource - `table` (table) - A table containing info about the atlas. Supported entries:
  • texture
    string | hash the path to the texture resource, e.g "/main/my_texture.texturec"
  • animations
    table a list of the animations in the atlas. Supports the following fields:
  • id
    string the id of the animation, used in e.g sprite.play_animation
  • width
    number the width of the animation
  • height
    number the height of the animation
  • frame_start
    number index to the first geometry of the animation. Indices are lua based and must be in the range of 1 .. in atlas.
  • frame_end
    number index to the last geometry of the animation (non-inclusive). Indices are lua based and must be in the range of 1 .. in atlas.
  • playback
    constant optional playback mode of the animation, the default value is go.PLAYBACK_ONCE_FORWARD
  • fps
    number optional fps of the animation, the default value is 30
  • flip_vertical
    boolean optional flip the animation vertically, the default value is false
  • flip_horizontal
    boolean optional flip the animation horizontally, the default value is false
  • geometries
    table A list of the geometries that should map to the texture data. Supports the following fields:
  • vertices
    table a list of the vertices in texture space of the geometry in the form {px0, py0, px1, py1, ..., pxn, pyn}
  • uvs
    table a list of the uv coordinates in texture space of the geometry in the form of {u0, v0, u1, v1, ..., un, vn}
  • indices
    table a list of the indices of the geometry in the form {i0, i1, i2, ..., in}. Each tripe in the list represents a triangle.
**Examples** Add a new animation to an existing atlas ``` function init(self) local data = resource.get_atlas("/main/my_atlas.a.texturesetc") local my_animation = { id = "my_new_animation", width = 128, height = 128, frame_start = 1, frame_end = 6, playback = go.PLAYBACK_LOOP_PINGPONG, fps = 8 } table.insert(data.animations, my_animation) resource.set_atlas("/main/my_atlas.a.texturesetc", data) end ```Sets atlas data for a 256x256 texture with a single animation being rendered as a quad ```lua function init(self) local params = { texture = "/main/my_256x256_texture.texturec", animations = { { id = "my_animation", width = 256, height = 256, frames = { 1 } } }, geometries = { { vertices = { 0, 0, 0, 256, 256, 256, 256, 0 }, uvs = { 0, 0, 0, 256, 256, 256, 256, 0 }, indices = { 0,1,2,0,2,3 } } } } resource.set_atlas("/main/test.a.texturesetc", params) end ``` ### resource.set_buffer *Type:* FUNCTION Sets the buffer of a resource. By default, setting the resource buffer will either copy the data from the incoming buffer object to the buffer stored in the destination resource, or make a new buffer object if the sizes between the source buffer and the destination buffer stored in the resource differs. In some cases, e.g performance reasons, it might be beneficial to just set the buffer object on the resource without copying or cloning. To achieve this, set the transfer_ownership flag to true in the argument table. Transferring ownership from a lua buffer to a resource with this function works exactly the same as resource.create_buffer: the destination resource will take ownership of the buffer held by the lua reference, i.e the buffer will not automatically be removed when the lua reference to the buffer is garbage collected. Note: When setting a buffer with transfer_ownership = true, the currently bound buffer in the resource will be destroyed. **Parameters** - `path` (hash | string) - The path to the resource - `buffer` (buffer) - The resource buffer - `table` (table) (optional) - A table containing info about how to set the buffer. Supported entries:
  • transfer_ownership
    boolean optional flag to determine wether or not the resource should take over ownership of the buffer object (default false)
**Examples** How to set the data from a buffer ``` local function fill_stream(stream, verts) for key, value in ipairs(verts) do stream[key] = verts[key] end end function init(self) local res_path = go.get("#mesh", "vertices") local positions = { 1, -1, 0, 1, 1, 0, -1, -1, 0 } local num_verts = #positions / 3 -- create a new buffer local buf = buffer.create(num_verts, { { name = hash("position"), type=buffer.VALUE_TYPE_FLOAT32, count = 3 } }) local buf = resource.get_buffer(res_path) local stream_positions = buffer.get_stream(buf, "position") fill_stream(stream_positions, positions) resource.set_buffer(res_path, buf) end ``` ### resource.set_sound *Type:* FUNCTION Update internal sound resource (wavc/oggc/opusc) with new data **Parameters** - `path` (hash | string) - The path to the resource - `buffer` (string) - A lua string containing the binary sound data ### resource.set_texture *Type:* FUNCTION Sets the pixel data for a specific texture. **Parameters** - `path` (hash | string) - The path to the resource - `table` (table) - A table containing info about the texture. Supported entries:
type
number The texture type. Supported values:
  • graphics.TEXTURE_TYPE_2D
  • graphics.TEXTURE_TYPE_IMAGE_2D
  • graphics.TEXTURE_TYPE_3D
  • graphics.TEXTURE_TYPE_IMAGE_3D
  • graphics.TEXTURE_TYPE_CUBE_MAP
width
number The width of the texture (in pixels)
height
number The width of the texture (in pixels)
format
number The texture format, note that some of these formats are platform specific. Supported values:
  • graphics.TEXTURE_FORMAT_LUMINANCE
  • graphics.TEXTURE_FORMAT_RGB
  • graphics.TEXTURE_FORMAT_RGBA
These constants might not be available on the device: - graphics.TEXTURE_FORMAT_RGB_PVRTC_2BPPV1 - graphics.TEXTURE_FORMAT_RGB_PVRTC_4BPPV1 - graphics.TEXTURE_FORMAT_RGBA_PVRTC_2BPPV1 - graphics.TEXTURE_FORMAT_RGBA_PVRTC_4BPPV1 - graphics.TEXTURE_FORMAT_RGB_ETC1 - graphics.TEXTURE_FORMAT_RGBA_ETC2 - graphics.TEXTURE_FORMAT_RGBA_ASTC_4X4 - graphics.TEXTURE_FORMAT_RGB_BC1 - graphics.TEXTURE_FORMAT_RGBA_BC3 - graphics.TEXTURE_FORMAT_R_BC4 - graphics.TEXTURE_FORMAT_RG_BC5 - graphics.TEXTURE_FORMAT_RGBA_BC7 - graphics.TEXTURE_FORMAT_RGB16F - graphics.TEXTURE_FORMAT_RGB32F - graphics.TEXTURE_FORMAT_RGBA16F - graphics.TEXTURE_FORMAT_RGBA32F - graphics.TEXTURE_FORMAT_R16F - graphics.TEXTURE_FORMAT_RG16F - graphics.TEXTURE_FORMAT_R32F - graphics.TEXTURE_FORMAT_RG32F You can test if the device supports these values by checking if a specific enum is nil or not:
if graphics.TEXTURE_FORMAT_RGBA16F ~= nil then
    -- it is safe to use this format
end
x
number optional x offset of the texture (in pixels)
y
number optional y offset of the texture (in pixels)
z
number optional z offset of the texture (in pixels). Only applies to 3D textures
page
number optional slice of the array texture. Only applies to 2D texture arrays. Zero-based
mipmap
number optional mipmap to upload the data to
compression_type
number optional specify the compression type for the data in the buffer object that holds the texture data. Defaults to graphics.COMPRESSION_TYPE_DEFAULT, i.e no compression. Supported values:
  • COMPRESSION_TYPE_DEFAULT
  • COMPRESSION_TYPE_BASIS_UASTC
- `buffer` (buffer) - The buffer of precreated pixel data To update a cube map texture you need to pass in six times the amount of data via the buffer, since a cube map has six sides! 3D Textures are currently only supported on OpenGL and Vulkan adapters. To check if your device supports 3D textures, use: ```lua if graphics.TEXTURE_TYPE_3D ~= nil then -- Device and graphics adapter support 3D textures end **Examples** How to set all pixels of an atlas ``` function init(self) self.height = 128 self.width = 128 self.buffer = buffer.create(self.width * self.height, { {name=hash("rgb"), type=buffer.VALUE_TYPE_UINT8, count=3} } ) self.stream = buffer.get_stream(self.buffer, hash("rgb")) for y=1,self.height do for x=1,self.width do local index = (y-1) * self.width * 3 + (x-1) * 3 + 1 self.stream[index + 0] = 0xff self.stream[index + 1] = 0x80 self.stream[index + 2] = 0x10 end end local resource_path = go.get("#model", "texture0") local args = { width=self.width, height=self.height, type=graphics.TEXTURE_TYPE_2D, format=graphics.TEXTURE_FORMAT_RGB, num_mip_maps=1 } resource.set_texture( resource_path, args, self.buffer ) end ```How to update a specific region of an atlas by using the x,y values. Assumes the already set atlas is a 128x128 texture. ```lua function init(self) self.x = 16 self.y = 16 self.height = 128 - self.x * 2 self.width = 128 - self.y * 2 self.buffer = buffer.create(self.width * self.height, { {name=hash("rgb"), type=buffer.VALUE_TYPE_UINT8, count=3} } ) self.stream = buffer.get_stream(self.buffer, hash("rgb")) for y=1,self.height do for x=1,self.width do local index = (y-1) * self.width * 3 + (x-1) * 3 + 1 self.stream[index + 0] = 0xff self.stream[index + 1] = 0x80 self.stream[index + 2] = 0x10 end end local resource_path = go.get("#model", "texture0") local args = { width=self.width, height=self.height, x=self.x, y=self.y, type=graphics.TEXTURE_TYPE_2D, format=graphics.TEXTURE_FORMAT_RGB, num_mip_maps=1 } resource.set_texture(resource_path, args, self.buffer ) end ```Update a texture from a buffer resource ```lua go.property("my_buffer", resource.buffer("/my_default_buffer.buffer")) function init(self) local resource_path = go.get("#model", "texture0") -- the "my_buffer" resource is expected to hold 128 * 128 * 3 bytes! local args = { width = 128, height = 128, type = graphics.TEXTURE_TYPE_2D, format = graphics.TEXTURE_FORMAT_RGB } -- Note that the extra resource.get_buffer call is a requirement here -- since the "self.my_buffer" is just pointing to a buffer resource path -- and not an actual buffer object or buffer resource. resource.set_texture(resource_path, args, resource.get_buffer(self.my_buffer)) end ```Update an existing 3D texture from a lua buffer ```lua function init(self) -- create a buffer that can hold the data of a 8x8x8 texture local tbuffer = buffer.create(8 * 8 * 8, { {name=hash("rgba"), type=buffer.VALUE_TYPE_FLOAT32, count=4} } ) local tstream = buffer.get_stream(tbuffer, hash("rgba")) -- populate the buffer with some data local index = 1 for z=1,8 do for y=1,8 do for x=1,8 do tstream[index + 0] = x tstream[index + 1] = y tstream[index + 2] = z tstream[index + 3] = 1.0 index = index + 4 end end end local t_args = { type = graphics.TEXTURE_TYPE_IMAGE_3D, width = 8, height = 8, depth = 8, format = resource.TEXTURE_FORMAT_RGBA32F } -- This expects that the texture resource "/my_3d_texture.texturec" already exists -- and is a 3D texture resource. To create a dynamic 3D texture resource -- use the "resource.create_texture" function. resource.set_texture("/my_3d_texture.texturec", t_args, tbuffer) endUpdate texture 2nd array page with loaded texture from png ```lua -- new_tex is resource handle of texture which was created via resource.create_resource local tex_path = "/bundle_resources/page_02.png" local data = sys.load_resource(tex_path) local buf = image.load_buffer(data) resource.set_texture(new_tex, { type = graphics.TEXTURE_TYPE_2D_ARRAY, width = buf.width, height = buf.height, page = 1, format = graphics.TEXTURE_FORMAT_RGB }, buf.buffer) go.set("#mesh", "texture0", new_tex) ``` ### resource.texture *Type:* FUNCTION Constructor-like function with two purposes: Load the specified resource as part of loading the script Return a hash to the run-time version of the resource This function can only be called within go.property function calls. **Parameters** - `path` (string) (optional) - optional resource path string to the resource **Returns** - `path` (hash) - a path hash to the binary version of the resource **Examples** Load a texture and set it to a model: ``` go.property("my_texture", resource.texture("/texture.png")) function init(self) go.set("#model", "texture0", self.my_texture) end ``` ### resource.tile_source *Type:* FUNCTION Constructor-like function with two purposes: Load the specified resource as part of loading the script Return a hash to the run-time version of the resource This function can only be called within go.property function calls. **Parameters** - `path` (string) (optional) - optional resource path string to the resource **Returns** - `path` (hash) - a path hash to the binary version of the resource **Examples** Load tile source and set it to a tile map: ``` go.property("my_tile_source", resource.tile_source("/tilesource.tilesource")) function init(self) go.set("#tilemap", "tile_source", self.my_tile_source) end ``` # LuaSocket {#apis:socket-lua} **Namespace:** `socket` **Language:** Lua **Type:** Defold Lua **File:** `luasocket.doc_h` **Source:** `engine/script/src/luasocket/luasocket.doc_h` [LuaSocket](https://github.com/diegonehab/luasocket) is a Lua extension library that provides support for the TCP and UDP transport layers. Defold provides the "socket" namespace in runtime, which contain the core C functionality. Additional LuaSocket support modules for SMTP, HTTP, FTP etc are not part of the core included, but can be easily added to a project and used. [icon:html5] On HTML5, the non-network helpers remain available, but TCP, UDP and `socket.select()` are not supported. Note the included helper module "socket.lua" in "builtins/scripts/socket.lua". Require this module to add some additional functions and shortcuts to the namespace: ```lua require "builtins.scripts.socket" ``` LuaSocket is Copyright © 2004-2007 Diego Nehab. All rights reserved. LuaSocket is free software, released under the MIT license (same license as the Lua core). ## API ### client *Type:* TYPEDEF TCP client object **Parameters** - `value` (userdata) ### client:close *Type:* FUNCTION Closes the TCP object. The internal socket used by the object is closed and the local address to which the object was bound is made available to other applications. No further operations (except for further calls to the close method) are allowed on a closed socket. It is important to close all used sockets once they are not needed, since, in many systems, each socket uses a file descriptor, which are limited system resources. Garbage-collected objects are automatically closed before destruction, though. ### client:dirty *Type:* FUNCTION Check the read buffer status. This is an internal method, any use is unlikely to be portable. **Returns** - `status` (boolean) - true if there is any data in the read buffer, false otherwise. ### client:getfd *Type:* FUNCTION Returns the underlying socket descriptor or handle associated to the object. This is an internal method, any use is unlikely to be portable. **Returns** - `handle` (number) - the descriptor or handle. In case the object has been closed, the return will be -1. ### client:getoption *Type:* FUNCTION Gets options for the TCP object. See client:setoption for description of the option names and values. **Parameters** - `option` (string) - the name of the option to get:
  • "keepalive"
  • "linger"
  • "reuseaddr"
  • "tcp-nodelay"
**Returns** - `value` (any | nil) - the option value, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### client:getpeername *Type:* FUNCTION Returns information about the remote side of a connected client object. It makes no sense to call this method on server objects. **Returns** - `info` (string) - a string with the IP address of the peer, the port number that peer is using for the connection, and the family ("inet" or "inet6"). In case of error, the method returns nil. ### client:getsockname *Type:* FUNCTION Returns the local address information associated to the object. **Returns** - `info` (string) - a string with local IP address, the local port number, and the family ("inet" or "inet6"). In case of error, the method returns nil. ### client:getstats *Type:* FUNCTION Returns accounting information on the socket, useful for throttling of bandwidth. **Returns** - `stats` (string) - a string with the number of bytes received, the number of bytes sent, and the age of the socket object in seconds. ### client:receive *Type:* FUNCTION Reads data from a client object, according to the specified read pattern. Patterns follow the Lua file I/O format, and the difference in performance between patterns is negligible. **Parameters** - `pattern` (string | number) (optional) - the read pattern that can be any of the following:
"*a"
reads from the socket until the connection is closed. No end-of-line translation is performed;
"*l"
reads a line of text from the socket. The line is terminated by a LF character (ASCII 10), optionally preceded by a CR character (ASCII 13). The CR and LF characters are not included in the returned line. In fact, all CR characters are ignored by the pattern. This is the default pattern;
number
causes the method to read a specified number of bytes from the socket.
- `prefix` (string) (optional) - an optional string to be concatenated to the beginning of any received data before return. **Returns** - `data` (string | nil) - the received pattern, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. The error message can be the string "closed" in case the connection was closed before the transmission was completed or the string "timeout" in case there was a timeout during the operation. - `partial` (string | nil) - a (possibly empty) string containing the partial that was received, or nil if no error occurred. ### client:send *Type:* FUNCTION Sends data through client object. The optional arguments i and j work exactly like the standard string.sub Lua function to allow the selection of a substring to be sent. Output is not buffered. For small strings, it is always better to concatenate them in Lua (with the .. operator) and send the result in one call instead of calling the method several times. **Parameters** - `data` (string) - the string to be sent. - `i` (number) (optional) - optional starting index of the string. - `j` (number) (optional) - optional end index of string. **Returns** - `index` (number | nil) - the index of the last byte within [i, j] that has been sent, or nil in case of error. Notice that, if i is 1 or absent, this is effectively the total number of bytes sent. - `error` (string | nil) - the error message, or nil if no error occurred. The error message can be "closed" in case the connection was closed before the transmission was completed or the string "timeout" in case there was a timeout during the operation. - `lastindex` (number | nil) - in case of error, the index of the last byte within [i, j] that has been sent. You might want to try again from the byte following that. nil if no error occurred. ### client:setfd *Type:* FUNCTION Sets the underling socket descriptor or handle associated to the object. The current one is simply replaced, not closed, and no other change to the object state is made **Parameters** - `handle` (number) - the descriptor or handle to set. ### client:setoption *Type:* FUNCTION Sets options for the TCP object. Options are only needed by low-level or time-critical applications. You should only modify an option if you are sure you need it. **Parameters** - `option` (string) - the name of the option to set. The value is provided in the value parameter:
"keepalive"
Setting this option to true enables the periodic transmission of messages on a connected socket. Should the connected party fail to respond to these messages, the connection is considered broken and processes using the socket are notified;
"linger"
Controls the action taken when unsent data are queued on a socket and a close is performed. The value is a table with the following keys:
  • boolean on
  • number timeout (seconds)
If the 'on' field is set to true, the system will block the process on the close attempt until it is able to transmit the data or until timeout has passed. If 'on' is false and a close is issued, the system will process the close in a manner that allows the process to continue as quickly as possible. It is not advised to set this to anything other than zero;
"reuseaddr"
Setting this option indicates that the rules used in validating addresses supplied in a call to bind should allow reuse of local addresses;
"tcp-nodelay"
Setting this option to true disables the Nagle's algorithm for the connection;
"ipv6-v6only"
Setting this option to true restricts an inet6 socket to sending and receiving only IPv6 packets.
- `value` (any) (optional) - the value to set for the specified option. **Returns** - `status` (number | nil) - the value 1, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### client:setstats *Type:* FUNCTION Resets accounting information on the socket, useful for throttling of bandwidth. **Parameters** - `received` (number) - the new number of bytes received. - `sent` (number) - the new number of bytes sent. - `age` (number) - the new age in seconds. **Returns** - `success` (number | nil) - the value 1 in case of success, or nil in case of error. ### client:settimeout *Type:* FUNCTION Changes the timeout values for the object. By default, all I/O operations are blocking. That is, any call to the methods send, receive, and accept will block indefinitely, until the operation completes. The settimeout method defines a limit on the amount of time the I/O methods can block. When a timeout is set and the specified amount of time has elapsed, the affected methods give up and fail with an error code. There are two timeout modes and both can be used together for fine tuning. Although timeout values have millisecond precision in LuaSocket, large blocks can cause I/O functions not to respect timeout values due to the time the library takes to transfer blocks to and from the OS and to and from the Lua interpreter. Also, function that accept host names and perform automatic name resolution might be blocked by the resolver for longer than the specified timeout value. **Parameters** - `value` (number) - the amount of time to wait, in seconds. The nil timeout value allows operations to block indefinitely. Negative timeout values have the same effect. - `mode` (string) (optional) - optional timeout mode to set:
"b"
block timeout. Specifies the upper limit on the amount of time LuaSocket can be blocked by the operating system while waiting for completion of any single I/O operation. This is the default mode;
"t"
total timeout. Specifies the upper limit on the amount of time LuaSocket can block a Lua script before returning from a call.
### client:shutdown *Type:* FUNCTION Shuts down part of a full-duplex connection. **Parameters** - `mode` (string) - which way of the connection should be shut down:
"both"
disallow further sends and receives on the object. This is the default mode;
"send"
disallow further sends on the object;
"receive"
disallow further receives on the object.
**Returns** - `status` (number) - the value 1. ### connected:close *Type:* FUNCTION Closes a UDP object. The internal socket used by the object is closed and the local address to which the object was bound is made available to other applications. No further operations (except for further calls to the close method) are allowed on a closed socket. It is important to close all used sockets once they are not needed, since, in many systems, each socket uses a file descriptor, which are limited system resources. Garbage-collected objects are automatically closed before destruction, though. ### connected:getoption *Type:* FUNCTION Gets an option value from the UDP object. See connected:setoption for description of the option names and values. **Parameters** - `option` (string) - the name of the option to get:
  • "dontroute"
  • "broadcast"
  • "reuseaddr"
  • "reuseport"
  • "ip-multicast-loop"
  • "ipv6-v6only"
  • "ip-multicast-if"
  • "ip-multicast-ttl"
  • "ip-add-membership"
  • "ip-drop-membership"
**Returns** - `value` (any | nil) - the option value, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### connected:getpeername *Type:* FUNCTION Retrieves information about the peer associated with a connected UDP object. It makes no sense to call this method on unconnected objects. **Returns** - `info` (string) - a string with the IP address of the peer, the port number that peer is using for the connection, and the family ("inet" or "inet6"). In case of error, the method returns nil. ### connected:getsockname *Type:* FUNCTION Returns the local address information associated to the object. UDP sockets are not bound to any address until the setsockname or the sendto method is called for the first time (in which case it is bound to an ephemeral port and the wild-card address). **Returns** - `info` (string) - a string with local IP address, a number with the local port, and the family ("inet" or "inet6"). In case of error, the method returns nil. ### connected:receive *Type:* FUNCTION Receives a datagram from the UDP object. If the UDP object is connected, only datagrams coming from the peer are accepted. Otherwise, the returned datagram can come from any host. **Parameters** - `size` (number) (optional) - optional maximum size of the datagram to be retrieved. If there are more than size bytes available in the datagram, the excess bytes are discarded. If there are less then size bytes available in the current datagram, the available bytes are returned. If size is omitted, the maximum datagram size is used (which is currently limited by the implementation to 8192 bytes). **Returns** - `datagram` (string | nil) - the received datagram, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### connected:send *Type:* FUNCTION Sends a datagram to the UDP peer of a connected object. In UDP, the send method never blocks and the only way it can fail is if the underlying transport layer refuses to send a message to the specified address (i.e. no interface accepts the address). **Parameters** - `datagram` (string) - a string with the datagram contents. The maximum datagram size for UDP is 64K minus IP layer overhead. However datagrams larger than the link layer packet size will be fragmented, which may deteriorate performance and/or reliability. **Returns** - `success` (number | nil) - the value 1 on success, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### connected:setoption *Type:* FUNCTION Sets options for the UDP object. Options are only needed by low-level or time-critical applications. You should only modify an option if you are sure you need it. **Parameters** - `option` (string) - the name of the option to set. The value is provided in the value parameter:
"dontroute"
Indicates that outgoing messages should bypass the standard routing facilities. Receives a boolean value;
"broadcast"
Requests permission to send broadcast datagrams on the socket. Receives a boolean value;
"reuseaddr"
Indicates that the rules used in validating addresses supplied in a bind call should allow reuse of local addresses. Receives a boolean value;
"reuseport"
Allows completely duplicate bindings by multiple processes if they all set "reuseport" before binding the port. Receives a boolean value;
"ip-multicast-loop"
Specifies whether or not a copy of an outgoing multicast datagram is delivered to the sending host as long as it is a member of the multicast group. Receives a boolean value;
"ipv6-v6only"
Specifies whether to restrict inet6 sockets to sending and receiving only IPv6 packets. Receive a boolean value;
"ip-multicast-if"
Sets the interface over which outgoing multicast datagrams are sent. Receives an IP address;
"ip-multicast-ttl"
Sets the Time To Live in the IP header for outgoing multicast datagrams. Receives a number;
"ip-add-membership": Joins the multicast group specified. Receives a table with fields:
  • string multiaddr (IP address)
  • string interface (IP address)
"'ip-drop-membership"`
Leaves the multicast group specified. Receives a table with fields:
  • string multiaddr (IP address)
  • string interface (IP address)
- `value` (any) (optional) - the value to set for the specified option. **Returns** - `status` (number | nil) - the value 1, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### connected:setpeername *Type:* FUNCTION Changes the peer of a UDP object. This method turns an unconnected UDP object into a connected UDP object or vice versa. For connected objects, outgoing datagrams will be sent to the specified peer, and datagrams received from other peers will be discarded by the OS. Connected UDP objects must use the send and receive methods instead of sendto and receivefrom. Since the address of the peer does not have to be passed to and from the OS, the use of connected UDP objects is recommended when the same peer is used for several transmissions and can result in up to 30% performance gains. **Parameters** - `"*"` (string) - if address is "*" and the object is connected, the peer association is removed and the object becomes an unconnected object again. **Returns** - `success` (number | nil) - the value 1 on success, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### connected:settimeout *Type:* FUNCTION Changes the timeout values for the object. By default, the receive and receivefrom operations are blocking. That is, any call to the methods will block indefinitely, until data arrives. The settimeout function defines a limit on the amount of time the functions can block. When a timeout is set and the specified amount of time has elapsed, the affected methods give up and fail with an error code. In UDP, the send and sendto methods never block (the datagram is just passed to the OS and the call returns immediately). Therefore, the settimeout method has no effect on them. **Parameters** - `value` (number) - the amount of time to wait, in seconds. The nil timeout value allows operations to block indefinitely. Negative timeout values have the same effect. ### master *Type:* TYPEDEF TCP master object **Parameters** - `value` (userdata) ### master:bind *Type:* FUNCTION Binds a master object to address and port on the local host. **Parameters** - `address` (string) - an IP address or a host name. If address is "*", the system binds to all local interfaces using the INADDR_ANY constant. - `port` (number) - the port to commect to, in the range [0..64K). If port is 0, the system automatically chooses an ephemeral port. **Returns** - `status` (number | nil) - the value 1, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### master:close *Type:* FUNCTION Closes the TCP object. The internal socket used by the object is closed and the local address to which the object was bound is made available to other applications. No further operations (except for further calls to the close method) are allowed on a closed socket. It is important to close all used sockets once they are not needed, since, in many systems, each socket uses a file descriptor, which are limited system resources. Garbage-collected objects are automatically closed before destruction, though. ### master:connect *Type:* FUNCTION Attempts to connect a master object to a remote host, transforming it into a client object. Client objects support methods send, receive, getsockname, getpeername, settimeout, and close. Note that the function socket.connect is available and is a shortcut for the creation of client sockets. **Parameters** - `address` (string) - an IP address or a host name. If address is "*", the system binds to all local interfaces using the INADDR_ANY constant. - `port` (number) - the port to commect to, in the range [0..64K). If port is 0, the system automatically chooses an ephemeral port. **Returns** - `status` (number | nil) - the value 1, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### master:dirty *Type:* FUNCTION Check the read buffer status. This is an internal method, any use is unlikely to be portable. **Returns** - `status` (boolean) - true if there is any data in the read buffer, false otherwise. ### master:getfd *Type:* FUNCTION Returns the underlying socket descriptor or handle associated to the object. This is an internal method, any use is unlikely to be portable. **Returns** - `handle` (number) - the descriptor or handle. In case the object has been closed, the return will be -1. ### master:getsockname *Type:* FUNCTION Returns the local address information associated to the object. **Returns** - `info` (string) - a string with local IP address, the local port number, and the family ("inet" or "inet6"). In case of error, the method returns nil. ### master:getstats *Type:* FUNCTION Returns accounting information on the socket, useful for throttling of bandwidth. **Returns** - `stats` (string) - a string with the number of bytes received, the number of bytes sent, and the age of the socket object in seconds. ### master:listen *Type:* FUNCTION Specifies the socket is willing to receive connections, transforming the object into a server object. Server objects support the accept, getsockname, setoption, settimeout, and close methods. **Parameters** - `backlog` (number) - the number of client connections that can be queued waiting for service. If the queue is full and another client attempts connection, the connection is refused. **Returns** - `status` (number | nil) - the value 1, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### master:setfd *Type:* FUNCTION Sets the underling socket descriptor or handle associated to the object. The current one is simply replaced, not closed, and no other change to the object state is made **Parameters** - `handle` (number) - the descriptor or handle to set. ### master:setstats *Type:* FUNCTION Resets accounting information on the socket, useful for throttling of bandwidth. **Parameters** - `received` (number) - the new number of bytes received. - `sent` (number) - the new number of bytes sent. - `age` (number) - the new age in seconds. **Returns** - `success` (number | nil) - the value 1 in case of success, or nil in case of error. ### master:settimeout *Type:* FUNCTION Changes the timeout values for the object. By default, all I/O operations are blocking. That is, any call to the methods send, receive, and accept will block indefinitely, until the operation completes. The settimeout method defines a limit on the amount of time the I/O methods can block. When a timeout is set and the specified amount of time has elapsed, the affected methods give up and fail with an error code. There are two timeout modes and both can be used together for fine tuning. Although timeout values have millisecond precision in LuaSocket, large blocks can cause I/O functions not to respect timeout values due to the time the library takes to transfer blocks to and from the OS and to and from the Lua interpreter. Also, function that accept host names and perform automatic name resolution might be blocked by the resolver for longer than the specified timeout value. **Parameters** - `value` (number) - the amount of time to wait, in seconds. The nil timeout value allows operations to block indefinitely. Negative timeout values have the same effect. - `mode` (string) (optional) - optional timeout mode to set:
"b"
block timeout. Specifies the upper limit on the amount of time LuaSocket can be blocked by the operating system while waiting for completion of any single I/O operation. This is the default mode;
"t"
total timeout. Specifies the upper limit on the amount of time LuaSocket can block a Lua script before returning from a call.
### server:accept *Type:* FUNCTION Waits for a remote connection on the server object and returns a client object representing that connection. Calling socket.select with a server object in the recvt parameter before a call to accept does not guarantee accept will return immediately. Use the settimeout method or accept might block until another client shows up. **Returns** - `tcp_client` (client | nil) - if a connection is successfully initiated, a client object is returned, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. The error is "timeout" if a timeout condition is met. ### server:close *Type:* FUNCTION Closes the TCP object. The internal socket used by the object is closed and the local address to which the object was bound is made available to other applications. No further operations (except for further calls to the close method) are allowed on a closed socket. It is important to close all used sockets once they are not needed, since, in many systems, each socket uses a file descriptor, which are limited system resources. Garbage-collected objects are automatically closed before destruction, though. ### server:dirty *Type:* FUNCTION Check the read buffer status. This is an internal method, any use is unlikely to be portable. **Returns** - `status` (boolean) - true if there is any data in the read buffer, false otherwise. ### server:getfd *Type:* FUNCTION Returns the underlying socket descriptor or handle associated to the object. This is an internal method, any use is unlikely to be portable. **Returns** - `handle` (number) - the descriptor or handle. In case the object has been closed, the return will be -1. ### server:getoption *Type:* FUNCTION Gets options for the TCP object. See server:setoption for description of the option names and values. **Parameters** - `option` (string) - the name of the option to get:
  • "keepalive"
  • "linger"
  • "reuseaddr"
  • "tcp-nodelay"
**Returns** - `value` (any | nil) - the option value, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### server:getsockname *Type:* FUNCTION Returns the local address information associated to the object. **Returns** - `info` (string) - a string with local IP address, the local port number, and the family ("inet" or "inet6"). In case of error, the method returns nil. ### server:getstats *Type:* FUNCTION Returns accounting information on the socket, useful for throttling of bandwidth. **Returns** - `stats` (string) - a string with the number of bytes received, the number of bytes sent, and the age of the socket object in seconds. ### server:setfd *Type:* FUNCTION Sets the underling socket descriptor or handle associated to the object. The current one is simply replaced, not closed, and no other change to the object state is made **Parameters** - `handle` (number) - the descriptor or handle to set. ### server:setoption *Type:* FUNCTION Sets options for the TCP object. Options are only needed by low-level or time-critical applications. You should only modify an option if you are sure you need it. **Parameters** - `option` (string) - the name of the option to set. The value is provided in the value parameter:
"keepalive"
Setting this option to true enables the periodic transmission of messages on a connected socket. Should the connected party fail to respond to these messages, the connection is considered broken and processes using the socket are notified;
"linger"
Controls the action taken when unsent data are queued on a socket and a close is performed. The value is a table with the following keys:
  • boolean on
  • number timeout (seconds)
If the 'on' field is set to true, the system will block the process on the close attempt until it is able to transmit the data or until timeout has passed. If 'on' is false and a close is issued, the system will process the close in a manner that allows the process to continue as quickly as possible. It is not advised to set this to anything other than zero;
"reuseaddr"
Setting this option indicates that the rules used in validating addresses supplied in a call to bind should allow reuse of local addresses;
"tcp-nodelay"
Setting this option to true disables the Nagle's algorithm for the connection;
"ipv6-v6only"
Setting this option to true restricts an inet6 socket to sending and receiving only IPv6 packets.
- `value` (any) (optional) - the value to set for the specified option. **Returns** - `status` (number | nil) - the value 1, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### server:setstats *Type:* FUNCTION Resets accounting information on the socket, useful for throttling of bandwidth. **Parameters** - `received` (number) - the new number of bytes received. - `sent` (number) - the new number of bytes sent. - `age` (number) - the new age in seconds. **Returns** - `success` (number | nil) - the value 1 in case of success, or nil in case of error. ### server:settimeout *Type:* FUNCTION Changes the timeout values for the object. By default, all I/O operations are blocking. That is, any call to the methods send, receive, and accept will block indefinitely, until the operation completes. The settimeout method defines a limit on the amount of time the I/O methods can block. When a timeout is set and the specified amount of time has elapsed, the affected methods give up and fail with an error code. There are two timeout modes and both can be used together for fine tuning. Although timeout values have millisecond precision in LuaSocket, large blocks can cause I/O functions not to respect timeout values due to the time the library takes to transfer blocks to and from the OS and to and from the Lua interpreter. Also, function that accept host names and perform automatic name resolution might be blocked by the resolver for longer than the specified timeout value. **Parameters** - `value` (number) - the amount of time to wait, in seconds. The nil timeout value allows operations to block indefinitely. Negative timeout values have the same effect. - `mode` (string) (optional) - optional timeout mode to set:
"b"
block timeout. Specifies the upper limit on the amount of time LuaSocket can be blocked by the operating system while waiting for completion of any single I/O operation. This is the default mode;
"t"
total timeout. Specifies the upper limit on the amount of time LuaSocket can block a Lua script before returning from a call.
### socket._SETSIZE *Type:* CONSTANT This constant contains the maximum number of sockets that the select function can handle. ### socket._VERSION *Type:* CONSTANT This constant has a string describing the current LuaSocket version. ### socket.connect *Type:* FUNCTION This function is a shortcut that creates and returns a TCP client object connected to a remote address at a given port. Optionally, the user can also specify the local address and port to bind (locaddr and locport), or restrict the socket family to "inet" or "inet6". Without specifying family to connect, whether a tcp or tcp6 connection is created depends on your system configuration. **Parameters** - `address` (string) - the address to connect to. - `port` (number) - the port to connect to. - `locaddr` (string) (optional) - optional local address to bind to. - `locport` (number) (optional) - optional local port to bind to. - `family` (string) (optional) - optional socket family to use, "inet" or "inet6". **Returns** - `tcp_client` (client | nil) - a new IPv6 TCP client object, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### socket.dns.getaddrinfo *Type:* FUNCTION This function converts a host name to IPv4 or IPv6 address. The supplied address can be an IPv4 or IPv6 address or host name. The function returns a table with all information returned by the resolver: ``` { [1] = { family = family-name-1, addr = address-1 }, ... [n] = { family = family-name-n, addr = address-n } } ``` Here, family contains the string "inet" for IPv4 addresses, and "inet6" for IPv6 addresses. In case of error, the function returns nil followed by an error message. **Parameters** - `address` (string) - a hostname or an IPv4 or IPv6 address. **Returns** - `resolved` (table | nil) - a table with all information returned by the resolver, or if an error occurs, nil. - `error` (string | nil) - the error message, or nil if no error occurred. ### socket.dns.gethostname *Type:* FUNCTION Returns the standard host name for the machine as a string. **Returns** - `hostname` (string) - the host name for the machine. ### socket.dns.getnameinfo *Type:* FUNCTION This function converts an address to host name. The supplied address can be an IPv4 or IPv6 address or host name. The function returns a table with all information returned by the resolver: ``` { [1] = host-name-1, ... [n] = host-name-n, } ``` **Parameters** - `address` (string) - a hostname or an IPv4 or IPv6 address. **Returns** - `resolved` (table | nil) - a table with all information returned by the resolver, or if an error occurs, nil. - `error` (string | nil) - the error message, or nil if no error occurred. ### socket.dns.tohostname *Type:* FUNCTION This function converts from an IPv4 address to host name. The address can be an IPv4 address or a host name. **Parameters** - `address` (string) - an IPv4 address or host name. **Returns** - `hostname` (string | nil) - the canonic host name of the given address, or nil in case of an error. - `resolved` (table | string) - a table with all information returned by the resolver, or if an error occurs, the error message string. ### socket.dns.toip *Type:* FUNCTION This function converts a host name to IPv4 address. The address can be an IP address or a host name. **Parameters** - `address` (string) - a hostname or an IP address. **Returns** - `ip_address` (string | nil) - the first IP address found for the hostname, or nil in case of an error. - `resolved` (table | string) - a table with all information returned by the resolver, or if an error occurs, the error message string. ### socket.gettime *Type:* FUNCTION Returns the time in seconds, relative to the system epoch (Unix epoch time since January 1, 1970 (UTC) or Windows file time since January 1, 1601 (UTC)). You should use the values returned by this function for relative measurements only. **Returns** - `seconds` (number) - the number of seconds elapsed. **Examples** How to use the gettime() function to measure running time: ``` t = socket.gettime() -- do stuff print(socket.gettime() - t .. " seconds elapsed") ``` ### socket.newtry *Type:* FUNCTION This function creates and returns a clean try function that allows for cleanup before the exception is raised. The finalizer function will be called in protected mode (see protect). **Parameters** - `finalizer` (function()) - a function that will be called before the try throws the exception. **Returns** - `try` (function) - the customized try function. **Examples** Perform operations on an open socket c: ``` -- create a try function that closes 'c' on error local try = socket.newtry(function() c:close() end) -- do everything reassured c will be closed try(c:send("hello there?\r\n")) local answer = try(c:receive()) ... try(c:send("good bye\r\n")) c:close() ``` ### socket.protect *Type:* FUNCTION Converts a function that throws exceptions into a safe function. This function only catches exceptions thrown by try functions. It does not catch normal Lua errors. Beware that if your function performs some illegal operation that raises an error, the protected function will catch the error and return it as a string. This is because try functions uses errors as the mechanism to throw exceptions. **Parameters** - `func` (function) - a function that calls a try function (or assert, or error) to throw exceptions. **Returns** - `safe_func` (function(function())) - an equivalent function that instead of throwing exceptions, returns nil followed by an error message. **Examples** ``` local dostuff = socket.protect(function() local try = socket.newtry() local c = try(socket.connect("myserver.com", 80)) try = socket.newtry(function() c:close() end) try(c:send("hello?\r\n")) local answer = try(c:receive()) c:close() end) local n, error = dostuff() ``` ### socket.select *Type:* FUNCTION The function returns a list with the sockets ready for reading, a list with the sockets ready for writing and an error message. The error message is "timeout" if a timeout condition was met and nil otherwise. The returned tables are doubly keyed both by integers and also by the sockets themselves, to simplify the test if a specific socket has changed status. Recvt and sendt parameters can be empty tables or nil. Non-socket values (or values with non-numeric indices) in these arrays will be silently ignored. The returned tables are doubly keyed both by integers and also by the sockets themselves, to simplify the test if a specific socket has changed status. This function can monitor a limited number of sockets, as defined by the constant socket._SETSIZE. This number may be as high as 1024 or as low as 64 by default, depending on the system. It is usually possible to change this at compile time. Invoking select with a larger number of sockets will raise an error. A known bug in WinSock causes select to fail on non-blocking TCP sockets. The function may return a socket as writable even though the socket is not ready for sending. Calling select with a server socket in the receive parameter before a call to accept does not guarantee accept will return immediately. Use the settimeout method or accept might block forever. If you close a socket and pass it to select, it will be ignored. (Using select with non-socket objects: Any object that implements getfd and dirty can be used with select, allowing objects from other libraries to be used within a socket.select driven loop.) **Parameters** - `recvt` (table) - array with the sockets to test for characters available for reading. - `sendt` (table) - array with sockets that are watched to see if it is OK to immediately write on them. - `timeout` (number) (optional) - the maximum amount of time (in seconds) to wait for a change in status. Nil, negative or omitted timeout value allows the function to block indefinitely. **Returns** - `sockets_r` (table) - a list with the sockets ready for reading. - `sockets_w` (table) - a list with the sockets ready for writing. - `error` (string | nil) - an error message. "timeout" if a timeout condition was met, otherwise nil. ### socket.skip *Type:* FUNCTION This function drops a number of arguments and returns the remaining. It is useful to avoid creation of dummy variables: D is the number of arguments to drop. Ret1 to retN are the arguments. The function returns retD+1 to retN. **Parameters** - `d` (number) - the number of arguments to drop. - `ret1` (any) (optional) - argument 1. - `ret2` (any) (optional) - argument 2. - `retN` (any) (optional) - argument N. **Returns** - `retD+1` (any | nil) - argument D+1. - `retD+2` (any | nil) - argument D+2. - `retN` (any | nil) - argument N. **Examples** Instead of doing the following with dummy variables: ``` -- get the status code and separator from SMTP server reply local dummy1, dummy2, code, sep = string.find(line, "^(%d%d%d)(.?)") ``` You can skip a number of variables: ``` -- get the status code and separator from SMTP server reply local code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)")) ``` ### socket.sleep *Type:* FUNCTION Freezes the program execution during a given amount of time. **Parameters** - `time` (number) - the number of seconds to sleep for. ### socket.tcp *Type:* FUNCTION Creates and returns an IPv4 TCP master object. A master object can be transformed into a server object with the method listen (after a call to bind) or into a client object with the method connect. The only other method supported by a master object is the close method. **Returns** - `tcp_master` (master | nil) - a new IPv4 TCP master object, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### socket.tcp6 *Type:* FUNCTION Creates and returns an IPv6 TCP master object. A master object can be transformed into a server object with the method listen (after a call to bind) or into a client object with the method connect. The only other method supported by a master object is the close method. Note: The TCP object returned will have the option "ipv6-v6only" set to true. **Returns** - `tcp_master` (master | nil) - a new IPv6 TCP master object, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### socket.udp *Type:* FUNCTION Creates and returns an unconnected IPv4 UDP object. Unconnected objects support the sendto, receive, receivefrom, getoption, getsockname, setoption, settimeout, setpeername, setsockname, and close methods. The setpeername method is used to connect the object. **Returns** - `udp_unconnected` (unconnected | nil) - a new unconnected IPv4 UDP object, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### socket.udp6 *Type:* FUNCTION Creates and returns an unconnected IPv6 UDP object. Unconnected objects support the sendto, receive, receivefrom, getoption, getsockname, setoption, settimeout, setpeername, setsockname, and close methods. The setpeername method is used to connect the object. Note: The UDP object returned will have the option "ipv6-v6only" set to true. **Returns** - `udp_unconnected` (unconnected | nil) - a new unconnected IPv6 UDP object, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### unconnected *Type:* TYPEDEF unconnected UDP object **Parameters** - `value` (userdata) ### unconnected:close *Type:* FUNCTION Closes a UDP object. The internal socket used by the object is closed and the local address to which the object was bound is made available to other applications. No further operations (except for further calls to the close method) are allowed on a closed socket. It is important to close all used sockets once they are not needed, since, in many systems, each socket uses a file descriptor, which are limited system resources. Garbage-collected objects are automatically closed before destruction, though. ### unconnected:getoption *Type:* FUNCTION Gets an option value from the UDP object. See unconnected:setoption for description of the option names and values. **Parameters** - `option` (string) - the name of the option to get:
  • "dontroute"
  • "broadcast"
  • "reuseaddr"
  • "reuseport"
  • "ip-multicast-loop"
  • "ipv6-v6only"
  • "ip-multicast-if"
  • "ip-multicast-ttl"
  • "ip-add-membership"
  • "ip-drop-membership"
**Returns** - `value` (any | nil) - the option value, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### unconnected:getsockname *Type:* FUNCTION Returns the local address information associated to the object. UDP sockets are not bound to any address until the setsockname or the sendto method is called for the first time (in which case it is bound to an ephemeral port and the wild-card address). **Returns** - `info` (string) - a string with local IP address, a number with the local port, and the family ("inet" or "inet6"). In case of error, the method returns nil. ### unconnected:receive *Type:* FUNCTION Receives a datagram from the UDP object. If the UDP object is connected, only datagrams coming from the peer are accepted. Otherwise, the returned datagram can come from any host. **Parameters** - `size` (number) (optional) - optional maximum size of the datagram to be retrieved. If there are more than size bytes available in the datagram, the excess bytes are discarded. If there are less then size bytes available in the current datagram, the available bytes are returned. If size is omitted, the maximum datagram size is used (which is currently limited by the implementation to 8192 bytes). **Returns** - `datagram` (string | nil) - the received datagram, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### unconnected:receivefrom *Type:* FUNCTION Works exactly as the receive method, except it returns the IP address and port as extra return values (and is therefore slightly less efficient). **Parameters** - `size` (number) (optional) - optional maximum size of the datagram to be retrieved. **Returns** - `datagram` (string | nil) - the received datagram, or nil in case of error. - `ip_or_error` (string) - the IP address, or the error message in case of error. - `port` (number | nil) - the port number, or nil in case of error. ### unconnected:sendto *Type:* FUNCTION Sends a datagram to the specified IP address and port number. In UDP, the send method never blocks and the only way it can fail is if the underlying transport layer refuses to send a message to the specified address (i.e. no interface accepts the address). **Parameters** - `datagram` (string) - a string with the datagram contents. The maximum datagram size for UDP is 64K minus IP layer overhead. However datagrams larger than the link layer packet size will be fragmented, which may deteriorate performance and/or reliability. - `ip` (string) - the IP address of the recipient. Host names are not allowed for performance reasons. - `port` (number) - the port number at the recipient. **Returns** - `success` (number | nil) - the value 1 on success, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### unconnected:setoption *Type:* FUNCTION Sets options for the UDP object. Options are only needed by low-level or time-critical applications. You should only modify an option if you are sure you need it. **Parameters** - `option` (string) - the name of the option to set. The value is provided in the value parameter:
"dontroute"
Indicates that outgoing messages should bypass the standard routing facilities. Receives a boolean value;
"broadcast"
Requests permission to send broadcast datagrams on the socket. Receives a boolean value;
"reuseaddr"
Indicates that the rules used in validating addresses supplied in a bind call should allow reuse of local addresses. Receives a boolean value;
"reuseport"
Allows completely duplicate bindings by multiple processes if they all set "reuseport" before binding the port. Receives a boolean value;
"ip-multicast-loop"
Specifies whether or not a copy of an outgoing multicast datagram is delivered to the sending host as long as it is a member of the multicast group. Receives a boolean value;
"ipv6-v6only"
Specifies whether to restrict inet6 sockets to sending and receiving only IPv6 packets. Receive a boolean value;
"ip-multicast-if"
Sets the interface over which outgoing multicast datagrams are sent. Receives an IP address;
"ip-multicast-ttl"
Sets the Time To Live in the IP header for outgoing multicast datagrams. Receives a number;
"ip-add-membership": Joins the multicast group specified. Receives a table with fields:
  • string multiaddr (IP address)
  • string interface (IP address)
"'ip-drop-membership"`
Leaves the multicast group specified. Receives a table with fields:
  • string multiaddr (IP address)
  • string interface (IP address)
- `value` (any) (optional) - the value to set for the specified option. **Returns** - `status` (number | nil) - the value 1, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### unconnected:setpeername *Type:* FUNCTION Changes the peer of a UDP object. This method turns an unconnected UDP object into a connected UDP object or vice versa. For connected objects, outgoing datagrams will be sent to the specified peer, and datagrams received from other peers will be discarded by the OS. Connected UDP objects must use the send and receive methods instead of sendto and receivefrom. Since the address of the peer does not have to be passed to and from the OS, the use of connected UDP objects is recommended when the same peer is used for several transmissions and can result in up to 30% performance gains. **Parameters** - `address` (string) - an IP address or a host name. - `port` (number) - the port number. **Returns** - `success` (number | nil) - the value 1 on success, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### unconnected:setsockname *Type:* FUNCTION Binds the UDP object to a local address. This method can only be called before any datagram is sent through the UDP object, and only once. Otherwise, the system automatically binds the object to all local interfaces and chooses an ephemeral port as soon as the first datagram is sent. After the local address is set, either automatically by the system or explicitly by setsockname, it cannot be changed. **Parameters** - `address` (string) - an IP address or a host name. If address is "*" the system binds to all local interfaces using the constant INADDR_ANY. - `port` (number) - the port number. If port is 0, the system chooses an ephemeral port. **Returns** - `success` (number | nil) - the value 1 on success, or nil in case of error. - `error` (string | nil) - the error message, or nil if no error occurred. ### unconnected:settimeout *Type:* FUNCTION Changes the timeout values for the object. By default, the receive and receivefrom operations are blocking. That is, any call to the methods will block indefinitely, until data arrives. The settimeout function defines a limit on the amount of time the functions can block. When a timeout is set and the specified amount of time has elapsed, the affected methods give up and fail with an error code. In UDP, the send and sendto methods never block (the datagram is just passed to the OS and the call returns immediately). Therefore, the settimeout method has no effect on them. **Parameters** - `value` (number) - the amount of time to wait, in seconds. The nil timeout value allows operations to block indefinitely. Negative timeout values have the same effect. # Sound {#apis:sound-lua} **Namespace:** `sound` **Language:** Lua **Type:** Defold Lua **File:** `script_sound.cpp` **Source:** `engine/gamesys/src/gamesys/scripts/script_sound.cpp` Functions and messages for controlling sound components and mixer groups. ## API ### gain *Type:* PROPERTY The gain on the sound-component. Note that gain is in linear scale, between 0 and 1. **Examples** ``` function init(self) local gain = go.get("#sound", "gain") go.set("#sound", "gain", gain * 1.5) end ``` ### pan *Type:* PROPERTY The pan on the sound-component. The valid range is from -1.0 to 1.0, representing -45 degrees left, to +45 degrees right. **Examples** ``` function init(self) local pan = go.get("#sound", "pan") go.set("#sound", "pan", pan * -1) end ``` ### play_sound *Type:* MESSAGE Post this message to a sound-component to make it play its sound. Multiple voices is supported. The limit is set to 32 voices per sound component. Note that gain is in linear scale, between 0 and 1. To get the dB value from the gain, use the formula 20 * log(gain). Inversely, to find the linear value from a dB value, use the formula 10db/20. A sound will continue to play even if the game object the sound component belonged to is deleted. You can send a stop_sound to stop the sound. play_id should be specified in case you want to receive sound_done or sound_stopped in on_message(). **Parameters** - `delay` (number) (optional) - delay in seconds before the sound starts playing, default is 0. - `gain` (number) (optional) - sound gain between 0 and 1, default is 1. - `play_id` (number) (optional) - the identifier of the sound, can be used to distinguish between consecutive plays from the same component. - `start_time` (number) (optional) - optional start offset (seconds). Mutually exclusive with start_frame. - `start_frame` (number) (optional) - optional start offset (frames). If both are provided, start_frame is used. **Examples** Assuming the script belongs to an instance with a sound-component with id "sound", this will make the component play its sound after 1 second: ``` msg.post("#sound", "play_sound", {delay = 1, gain = 0.5}) ``` ``` -- use `play_id` and `msg.post()` if you want to recieve `sound_done` or `sound_stopped` in on_message() function init() msg.post("#sound", "play_sound", {play_id = 1, delay = 1, gain = 0.5}) end function on_message(self, message_id, message) if message_id == hash("sound_done") then print("Sound play id: "..message.play_id) end end ``` ### set_gain *Type:* MESSAGE Post this message to a sound-component to set gain on all active playing voices. Note that gain is in linear scale, between 0 and 1. To get the dB value from the gain, use the formula 20 * log(gain). Inversely, to find the linear value from a dB value, use the formula 10db/20. **Parameters** - `gain` (number) (optional) - sound gain between 0 and 1, default is 1. **Examples** Assuming the script belongs to an instance with a sound-component with id "sound", this will set the gain to 0.5 ``` msg.post("#sound", "set_gain", {gain = 0.5}) ``` ### sound *Type:* PROPERTY The sound data used when playing the sound. The type of the property is hash. **Examples** How to change the sound: ``` function init(self) -- load a wav file bundled as a custom resource local wav = sys.load_resource("foo.wav") -- get resource path to the sound component local resource_path = go.get("#sound", "sound") -- update the resource with the loaded wav file resource.set_sound(resource_path, wav) -- play the updated sound sound.play("#sound") end ``` ### sound.get_group_gain *Type:* FUNCTION Get mixer group gain **Parameters** - `group` (string | hash) - group name **Returns** - `gain` (number) - gain in [0 1] range ([-60dB.. 0dB]) **Examples** Get the mixer group gain for the "soundfx" and convert to dB: ``` local gain = sound.get_group_gain("soundfx") local gain_db = 60 * gain ``` ### sound.get_group_name *Type:* FUNCTION Get a mixer group name as a string. This function is to be used for debugging and development tooling only. The function does a reverse hash lookup, which does not return a proper string value when the game is built in release mode. **Parameters** - `group` (string | hash) - group name **Returns** - `name` (string) - group name **Examples** Get the mixer group string names so we can show them as labels on a dev mixer overlay: ``` local groups = sound.get_groups() for _,group in ipairs(groups) do local name = sound.get_group_name(group) msg.post("/mixer_overlay#gui", "set_mixer_label", { group = group, label = name}) end ``` ### sound.get_groups *Type:* FUNCTION Get a table of all mixer group names (hashes). **Returns** - `groups` (table) - table of mixer group names **Examples** Get the mixer groups, set all gains to 0 except for "master" and "soundfx" where gain is set to 1: ``` local groups = sound.get_groups() for _,group in ipairs(groups) do if group == hash("master") or group == hash("soundfx") then sound.set_group_gain(group, 1) else sound.set_group_gain(group, 0) end end ``` ### sound.get_peak *Type:* FUNCTION Get peak value from mixer group. Note that gain is in linear scale, between 0 and 1. To get the dB value from the gain, use the formula 20 * log(gain). Inversely, to find the linear value from a dB value, use the formula 10db/20. Also note that the returned value might be an approximation and in particular the effective window might be larger than specified. **Parameters** - `group` (string | hash) - group name - `window` (number) - window length in seconds **Returns** - `peak_l` (number) - peak value for left channel - `peak_r` (number) - peak value for right channel **Examples** Get the peak gain from the "master" group and convert to dB for displaying: ``` local left_p, right_p = sound.get_peak("master", 0.1) left_p_db = 20 * log(left_p) right_p_db = 20 * log(right_p) ``` ### sound.get_rms *Type:* FUNCTION Get RMS (Root Mean Square) value from mixer group. This value is the square root of the mean (average) value of the squared function of the instantaneous values. For instance: for a sinewave signal with a peak gain of -1.94 dB (0.8 linear), the RMS is 0.8 × 1/sqrt(2) which is about 0.566. Note the returned value might be an approximation and in particular the effective window might be larger than specified. **Parameters** - `group` (string | hash) - group name - `window` (number) - window length in seconds **Returns** - `rms_l` (number) - RMS value for left channel - `rms_r` (number) - RMS value for right channel **Examples** Get the RMS from the "master" group where a mono -1.94 dB sinewave is playing: ``` local rms = sound.get_rms("master", 0.1) -- throw away right channel. print(rms) --> 0.56555819511414 ``` ### sound.is_music_playing *Type:* FUNCTION Checks if background music is playing, e.g. from iTunes. On non mobile platforms, this function always return false. On Android you can only get a correct reading of this state if your game is not playing any sounds itself. This is a limitation in the Android SDK. If your game is playing any sounds, even with a gain of zero, this function will return false. The best time to call this function is: In the init function of your main collection script before any sounds are triggered In a window listener callback when the window.WINDOW_EVENT_FOCUS_GAINED event is received Both those times will give you a correct reading of the state even when your application is swapped out and in while playing sounds and it works equally well on Android and iOS. **Returns** - `playing` (boolean) - true if music is playing, otherwise false. **Examples** If music is playing, mute "master": ``` if sound.is_music_playing() then -- mute "master" sound.set_group_gain("master", 0) end ``` ### sound.is_phone_call_active *Type:* FUNCTION Checks if a phone call is active. If there is an active phone call all other sounds will be muted until the phone call is finished. On non mobile platforms, this function always return false. **Returns** - `call_active` (boolean) - true if there is an active phone call, false otherwise. **Examples** Test if a phone call is on-going: ``` if sound.is_phone_call_active() then -- do something sensible. end ``` ### sound.pause *Type:* FUNCTION Pause all active voices **Parameters** - `url` (string | hash | url) - the sound that should pause - `pause` (boolean) - true if the sound should pause **Examples** Assuming the script belongs to an instance with a sound-component with id "sound", this will make the component pause all playing voices: ``` sound.pause("#sound", true) ``` ### sound.play *Type:* FUNCTION Make the sound component play its sound. Multiple voices are supported. The limit is set to 32 voices per sound component. A sound will continue to play even if the game object the sound component belonged to is deleted. You can call sound.stop() to stop the sound. **Notes** - Sounds are panned using a constant power panning (non linear fade). 0 means left/right channels are balanced at 71%/71% each. At -1 (full left) the channels are at 100%/0%, and 1 they're at 0%/100%. **Parameters** - `url` (string | hash | url) - the sound that should play - `play_properties` (table) (optional) -
optional table with properties:
delay
number delay in seconds before the sound starts playing, default is 0.
gain
number sound gain between 0 and 1, default is 1. The final gain of the sound will be a combination of this gain, the group gain and the master gain.
pan
number sound pan between -1 and 1, default is 0. The final pan of the sound will be an addition of this pan and the sound pan.
speed
number sound speed where 1.0 is normal speed, 0.5 is half speed and 2.0 is double speed. Valid range is 0.0 to 50.0. The final speed of the sound will be a multiplication of this speed and the sound speed.
start_time
number start playback offset (seconds). Optional, mutually exclusive with start_frame.
start_frame
number start playback offset (frames/samples). Optional, mutually exclusive with start_time. If both are provided, start_frame is used.
- `complete_function` (function(self, message_id, message, sender)) (optional) - function to call when the sound has finished playing or stopped manually via sound.stop.
self
object The current object.
message_id
hash The name of the completion message, which can be either "sound_done" if the sound has finished playing, or "sound_stopped" if it was stopped manually.
message
table Information about the completion:
  • number play_id - the sequential play identifier that was given by the sound.play function.
sender
url The invoker of the callback: the sound component.
**Returns** - `play_id` (number) - The identifier for the sound voice **Examples** Assuming the script belongs to an instance with a sound-component with id "sound", this will make the component play its sound after 1 second: ``` sound.play("#sound", { delay = 1, gain = 0.9, pan = -1.0 } ) ``` Using the callback argument, you can chain several sounds together: ``` local function sound_done(self, message_id, message, sender) -- play 'boom' sound fx when the countdown has completed if message_id == hash("sound_done") and message.play_id == self.countdown_id then sound.play("#boom", nil, sound_done) end end function init(self) self.countdown_id = sound.play("#countdown", nil, sound_done) end ``` ### sound.set_gain *Type:* FUNCTION Set gain on all active playing voices of a sound. **Parameters** - `url` (string | hash | url) - the sound to set the gain of - `gain` (number) (optional) - sound gain between 0 and 1 [-60dB .. 0dB]. The final gain of the sound will be a combination of this gain, the group gain and the master gain. **Examples** Assuming the script belongs to an instance with a sound-component with id "sound", this will set the gain to 0.9 ``` sound.set_gain("#sound", 0.9) ``` ### sound.set_group_gain *Type:* FUNCTION Set mixer group gain **Parameters** - `group` (string | hash) - group name - `gain` (number) - gain in range [0..1] mapped to [0 .. -60dB] **Examples** Set mixer group gain on the "soundfx" group to 50% (-30dB): ``` sound.set_group_gain("soundfx", 0.5) ``` ### sound.set_pan *Type:* FUNCTION Set panning on all active playing voices of a sound. The valid range is from -1.0 to 1.0, representing -45 degrees left, to +45 degrees right. **Notes** - Sounds are panned using a constant power panning (non linear fade). 0 means left/right channels are balanced at 71%/71% each. At -1 (full left) the channels are at 100%/0%, and 1 they're at 0%/100%. **Parameters** - `url` (string | hash | url) - the sound to set the panning value to - `pan` (number) (optional) - sound panning between -1.0 and 1.0 **Examples** Assuming the script belongs to an instance with a sound-component with id "sound", this will set the gain to 0.5 ``` sound.set_pan("#sound", 0.5) -- pan to the right ``` ### sound.stop *Type:* FUNCTION Stop playing all active voices or just one voice if play_id provided **Parameters** - `url` (string | hash | url) - the sound component that should stop - `stop_properties` (table) (optional) -
optional table with properties:
play_id
number the sequential play identifier that should be stopped (was given by the sound.play() function)
**Examples** Assuming the script belongs to an instance with a sound-component with id "sound", this will make the component stop all playing voices: ``` sound.stop("#sound") local id = sound.play("#sound") sound.stop("#sound", {play_id = id}) ``` ### sound_done *Type:* MESSAGE This message is sent back to the sender of a play_sound message if the sound could be played to completion and a play_id was provided with the play_sound message. **Parameters** - `play_id` (number) (optional) - id number supplied when the message was posted. ### sound_stopped *Type:* MESSAGE This message is sent back to the sender of a play_sound message, if the sound has been manually stopped and a play_id was provided with the play_sound message. **Parameters** - `play_id` (number) (optional) - id number supplied when the message was posted. ### speed *Type:* PROPERTY The speed on the sound-component where 1.0 is normal speed, 0.5 is half speed and 2.0 is double speed. Valid range is 0.0 to 50.0. **Examples** ``` function init(self) local speed = go.get("#sound", "speed") go.set("#sound", "speed", speed * 0.5) end ``` ### stop_sound *Type:* MESSAGE Post this message to a sound-component to make it stop playing all active voices **Examples** Assuming the script belongs to an instance with a sound-component with id "sound", this will make the component stop all playing voices: ``` msg.post("#sound", "stop_sound") ``` # Sprite {#apis:sprite-lua} **Namespace:** `sprite` **Language:** Lua **Type:** Defold Lua **File:** `sprite_ddf.proto` **Source:** `engine/gamesys/proto/gamesys/sprite_ddf.proto` Sprite API documentation ## API ### animation *Type:* PROPERTY READ ONLY The current animation id. An animation that plays currently for the sprite. The type of the property is hash. **Examples** How to get the animation on component "sprite": ``` function init(self) local animation = go.get("#sprite", "animation") end ``` ### animation_done *Type:* MESSAGE This message is sent to the sender of a play_animation message when the animation has completed. Note that this message is sent only for animations that play with the following playback modes: Once Forward Once Backward Once Ping Pong See play_animation for more information and examples of how to use this message. **Parameters** - `current_tile` (number) - the current tile of the sprite - `id` (hash) - id of the animation that was completed **Examples** How to sequence two animations together. ``` function init(self) -- play jump animation at init msg.post("#sprite", "play_animation", {id = hash("jump")}) end function on_message(self, message_id, message, sender) -- check for animation done response if message_id == hash("animation_done") then -- start the walk animation msg.post("#sprite", "play_animation", { id = hash("walk") }) end end ``` ### cursor *Type:* PROPERTY The normalized animation cursor. The type of the property is number. **Examples** How to get the normalized cursor value: ``` function init(self) -- Get the cursor value on component "sprite" local cursor = go.get("#sprite", "cursor") end ``` How to animate the cursor from 0.0 to 1.0 using linear easing for 2.0 seconds: ``` function init(self) -- Set the cursor on component "sprite" to make the animation go from 0 go.set("#sprite", "cursor", 0.0) -- Animate the cursor value go.animate("#sprite", "cursor", go.PLAYBACK_LOOP_FORWARD, 1.0, go.EASING_LINEAR, 2) end ``` ### frame_count *Type:* PROPERTY READ ONLY The frame count of the currently playing animation. **Examples** How to get the frame_count on component "sprite": ``` function init(self) local frame_count = go.get("#sprite", "frame_count") end ``` ### image *Type:* PROPERTY The image used when rendering the sprite. The type of the property is hash. **Examples** How to set image using a script property (see resource.atlas) ``` go.property("my_image", resource.atlas("/atlas.atlas")) function init(self) go.set("#sprite", "image", self.my_image) end ``` See resource.set_texture for an example on how to set the texture of an atlas. ### material *Type:* PROPERTY The material used when rendering the sprite. The type of the property is hash. **Examples** How to set material using a script property (see resource.material) ``` go.property("my_material", resource.material("/material.material")) function init(self) go.set("#sprite", "material", self.my_material) end ``` ### play_animation *Type:* MESSAGE Post this message to a sprite component to make it play an animation from its tile set. **Parameters** - `id` (hash) - the id of the animation to play - `offset` (number) - the normalized initial value of the animation cursor when the animation starts playing - `playback_rate` (number) - the rate with which the animation will be played. Must be positive **Examples** In the example, it is assumed that the instance of the script has a sprite-component with id "sprite". The sprite itself is assumed to be bound to a tile set with animations "walk" and "jump". ``` msg.post("#sprite", "play_animation", {id = hash("jump")}) ``` ### playback_rate *Type:* PROPERTY The animation playback rate. A multiplier to the animation playback rate. The type of the property is number. The playback_rate is a non-negative number, a negative value will be clamped to 0. **Examples** How to set the playback_rate on component "sprite" to play at double the current speed: ``` function init(self) -- Get the current value on component "sprite" playback_rate = go.get("#sprite", "playback_rate") -- Set the playback_rate to double the previous value. go.set("#sprite", "playback_rate", playback_rate * 2) end ``` ### scale *Type:* PROPERTY The non-uniform scale of the sprite. The type of the property is vector3. **Examples** How to scale a sprite independently along the X and Y axis: ``` function init(self) -- Double the y-axis scaling on component "sprite" local yscale = go.get("#sprite", "scale.y") go.set("#sprite", "scale.y", yscale * 2) end ``` ### size *Type:* PROPERTY The size of the sprite, not allowing for any additional scaling that may be applied. The type of the property is vector3. It is not possible to set the size if the size mode of the sprite is set to auto. **Examples** How to query a sprite's size, either as a vector or selecting a specific dimension: ``` function init(self) -- get size from component "sprite" local size = go.get("#sprite", "size") local sx = go.get("#sprite", "size.x") -- do something useful assert(size.x == sx) end ``` ### slice *Type:* PROPERTY The slice values of the sprite. The type of the property is a vector4 that corresponds to the left, top, right, bottom values of the sprite in the editor. It is not possible to set the slice property if the size mode of the sprite is set to auto. **Examples** How to query a sprite's slice values, either as a vector or selecting a specific dimension: ``` function init(self) local slice = go.get("#sprite", "slice") local slicex = go.get("#sprite", "slice.x") assert(slice.x == slicex) end ``` Animate the slice property with go.animate: ``` function init(self) -- animate the entire slice vector at once go.animate("#sprite", "slice", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(96, 96, 96, 96), go.EASING_INCUBIC, 2) -- or animate a single component go.animate("#sprite", "slice.y", go.PLAYBACK_LOOP_PINGPONG, 32, go.EASING_INCUBIC, 8) end ``` ### sprite.play_flipbook *Type:* FUNCTION Play an animation on a sprite component from its tile set An optional completion callback function can be provided that will be called when the animation has completed playing. If no function is provided, a animation_done message is sent to the script that started the animation. **Parameters** - `url` (string | hash | url) - the sprite that should play the animation - `id` (string | hash) - hashed id of the animation to play - `complete_function` (function(self, message_id, message, sender)) (optional) - function to call when the animation has completed.
self
object The current object.
message_id
hash The name of the completion message, "animation_done".
message
table Information about the completion:
  • number current_tile - the current tile of the sprite.
  • hash id - id of the animation that was completed.
sender
url The invoker of the callback: the sprite component.
- `play_properties` (table) (optional) - optional table with properties:
offset
number the normalized initial value of the animation cursor when the animation starts playing.
playback_rate
number the rate with which the animation will be played. Must be positive.
**Examples** The following examples assumes that the model has id "sprite". How to play the "jump" animation followed by the "run" animation: ``` local function anim_done(self, message_id, message, sender) if message_id == hash("animation_done") then if message.id == hash("jump") then -- jump animation done, chain with "run" sprite.play_flipbook(url, "run") end end end ``` ``` function init(self) local url = msg.url("#sprite") sprite.play_flipbook(url, "jump", anim_done) end ``` ### sprite.set_hflip *Type:* FUNCTION Sets horizontal flipping of the provided sprite's animations. The sprite is identified by its URL. If the currently playing animation is flipped by default, flipping it again will make it appear like the original texture. **Parameters** - `url` (string | hash | url) - the sprite that should flip its animations - `flip` (boolean) - true if the sprite should flip its animations, false if not **Examples** How to flip a sprite so it faces the horizontal movement: ``` function update(self, dt) -- calculate self.velocity somehow sprite.set_hflip("#sprite", self.velocity.x < 0) end ``` It is assumed that the sprite component has id "sprite" and that the original animations faces right. ### sprite.set_vflip *Type:* FUNCTION Sets vertical flipping of the provided sprite's animations. The sprite is identified by its URL. If the currently playing animation is flipped by default, flipping it again will make it appear like the original texture. **Parameters** - `url` (string | hash | url) - the sprite that should flip its animations - `flip` (boolean) - true if the sprite should flip its animations, false if not **Examples** How to flip a sprite in a game which negates gravity as a game mechanic: ``` function update(self, dt) -- calculate self.up_side_down somehow, then: sprite.set_vflip("#sprite", self.up_side_down) end ``` It is assumed that the sprite component has id "sprite" and that the original animations are up-right. # String {#apis:string-lua} **Namespace:** `string` **Language:** Lua **Type:** Defold Lua **File:** `lua_string.doc_h` **Source:** `engine/lua/src/lua_string.doc_h` Documentation for the Lua string standard library. From [Lua 5.1 Reference Manual](https://www.lua.org/manual/5.1/) by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes. Copyright © 2006-2012 Lua.org, PUC-Rio. Freely available under the terms of the [Lua license](https://www.lua.org/license.html). ### Patterns _Character Class:_ A character class is used to represent a set of characters. The following combinations are allowed in describing a character class: x : (where x is not one of the magic characters `^$()%.[]*+-?`) represents the character x itself. `.` : (a dot) represents all characters. `%a` : represents all letters. `%c` : represents all control characters. `%d` : represents all digits. `%l` : represents all lowercase letters. `%p` : represents all punctuation characters. `%s` : represents all space characters. `%u` : represents all uppercase letters. `%w` : represents all alphanumeric characters. `%x` : represents all hexadecimal digits. `%z` : represents the character with representation 0. `%x` : (where x is any non-alphanumeric character) represents the character x. This is the standard way to escape the magic characters. Any punctuation character (even the non magic) can be preceded by a '%' when used to represent itself in a pattern. `[set]` : represents the class which is the union of all characters in set. A range of characters can be specified by separating the end characters of the range with a '-'. All classes `%`x described above can also be used as components in set. All other characters in set represent themselves. For example, `[%w_]` (or `[_%w]`) represents all alphanumeric characters plus the underscore, `[0-7]` represents the octal digits, and `[0-7%l%-]` represents the octal digits plus the lowercase letters plus the '-' character. The interaction between ranges and classes is not defined. Therefore, patterns like `[%a-z]` or `[a-%%]` have no meaning. `[^set]` : represents the complement of set, where set is interpreted as above. For all classes represented by single letters (`%a`, `%c`, etc.), the corresponding uppercase letter represents the complement of the class. For instance, `%S` represents all non-space characters. The definitions of letter, space, and other character groups depend on the current locale. In particular, the class `[a-z]` may not be equivalent to `%l`. _Pattern Item:_ A pattern item can be - a single character class, which matches any single character in the class; - a single character class followed by '*', which matches 0 or more repetitions of characters in the class. These repetition items will always match the longest possible sequence; - a single character class followed by '+', which matches 1 or more repetitions of characters in the class. These repetition items will always match the longest possible sequence; - a single character class followed by '-', which also matches 0 or more repetitions of characters in the class. Unlike '*', these repetition items will always match the shortest possible sequence; - a single character class followed by '?', which matches 0 or 1 occurrence of a character in the class; - `%n`, for n between 1 and 9; such item matches a substring equal to the n-th captured string (see below); - `%bxy`, where x and y are two distinct characters; such item matches strings that start with x, end with y, and where the x and y are balanced. This means that, if one reads the string from left to right, counting +1 for an x and -1 for a y, the ending y is the first y where the count reaches 0. For instance, the item `%b()` matches expressions with balanced parentheses. _Pattern:_ A pattern is a sequence of pattern items. A '^' at the beginning of a pattern anchors the match at the beginning of the subject string. A '$' at the end of a pattern anchors the match at the end of the subject string. At other positions, '^' and '$' have no special meaning and represent themselves. _Captures:_ A pattern can contain sub-patterns enclosed in parentheses; they describe captures. When a match succeeds, the substrings of the subject string that match captures are stored (captured) for future use. Captures are numbered according to their left parentheses. For instance, in the pattern `"(a*(.)%w(%s*))"`, the part of the string matching `"a*(.)%w(%s*)"` is stored as the first capture (and therefore has number 1); the character matching "." is captured with number 2, and the part matching "%s*" has number 3. As a special case, the empty capture `()` captures the current string position (a number). For instance, if we apply the pattern `"()aa()"` on the string `"flaaap"`, there will be two captures: 3 and 5. A pattern cannot contain embedded zeros. Use `%z` instead. ## API ### string.byte *Type:* FUNCTION Returns the internal numerical codes of the characters s[i], s[i+1], ..., s[j]. The default value for i is 1; the default value for j is i. Note that numerical codes are not necessarily portable across platforms. **Parameters** - `s` (string) - `i` (number) (optional) - `j` (number) (optional) ### string.char *Type:* FUNCTION Receives zero or more integers. Returns a string with length equal to the number of arguments, in which each character has the internal numerical code equal to its corresponding argument. Note that numerical codes are not necessarily portable across platforms. **Parameters** - `...` ### string.dump *Type:* FUNCTION Returns a string containing a binary representation of the given function, so that a later loadstring on this string returns a copy of the function. function must be a Lua function without upvalues. **Parameters** - `function` (function) ### string.find *Type:* FUNCTION Looks for the first match of pattern in the string s. If it finds a match, then find returns the indices of s where this occurrence starts and ends; otherwise, it returns nil. A third, optional numerical argument init specifies where to start the search; its default value is 1 and can be negative. A value of true as a fourth, optional argument plain turns off the pattern matching facilities, so the function does a plain "find substring" operation, with no characters in pattern being considered "magic". Note that if plain is given, then init must be given as well. If the pattern has captures, then in a successful match the captured values are also returned, after the two indices. **Parameters** - `s` (string) - `pattern` (string) - `init` (number) (optional) - `plain` (boolean) (optional) ### string.format *Type:* FUNCTION Returns a formatted version of its variable number of arguments following the description given in its first argument (which must be a string). The format string follows the same rules as the printf family of standard C functions. The only differences are that the options/modifiers *, l, L, n, p, and h are not supported and that there is an extra option, q. The q option formats a string in a form suitable to be safely read back by the Lua interpreter: the string is written between double quotes, and all double quotes, newlines, embedded zeros, and backslashes in the string are correctly escaped when written. For instance, the call ``` string.format('%q', 'a string with "quotes" and \n new line') ``` will produce the string: ``` "a string with \"quotes\" and \ new line" ``` The options c, d, E, e, f, g, G, i, o, u, X, and x all expect a number as argument, whereas q and s expect a string. This function does not accept string values containing embedded zeros, except as arguments to the q option. **Parameters** - `formatstring` (string) - `...` ### string.gmatch *Type:* FUNCTION Returns an iterator function that, each time it is called, returns the next captures from pattern over string s. If pattern specifies no captures, then the whole match is produced in each call. As an example, the following loop ``` s = "hello world from Lua" for w in string.gmatch(s, "%a+") do print(w) end ``` will iterate over all the words from string s, printing one per line. The next example collects all pairs key=value from the given string into a table: ``` t = {} s = "from=world, to=Lua" for k, v in string.gmatch(s, "(%w+)=(%w+)") do t[k] = v end ``` For this function, a '^' at the start of a pattern does not work as an anchor, as this would prevent the iteration. **Parameters** - `s` (string) - `pattern` (string) ### string.gsub *Type:* FUNCTION Returns a copy of s in which all (or the first n, if given) occurrences of the pattern have been replaced by a replacement string specified by repl, which can be a string, a table, or a function. gsub also returns, as its second value, the total number of matches that occurred. If repl is a string, then its value is used for replacement. The character % works as an escape character: any sequence in repl of the form %n, with n between 1 and 9, stands for the value of the n-th captured substring (see below). The sequence %0 stands for the whole match. The sequence %% stands for a single %. If repl is a table, then the table is queried for every match, using the first capture as the key; if the pattern specifies no captures, then the whole match is used as the key. If repl is a function, then this function is called every time a match occurs, with all captured substrings passed as arguments, in order; if the pattern specifies no captures, then the whole match is passed as a sole argument. If the value returned by the table query or by the function call is a string or a number, then it is used as the replacement string; otherwise, if it is false or nil, then there is no replacement (that is, the original match is kept in the string). Here are some examples: ``` x = string.gsub("hello world", "(%w+)", "%1 %1") --> x="hello hello world world" x = string.gsub("hello world", "%w+", "%0 %0", 1) --> x="hello hello world" x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1") --> x="world hello Lua from" x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv) --> x="home = /home/roberto, user = roberto" x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s) return loadstring(s)() end) --> x="4+5 = 9" local t = {name="lua", version="5.1"} x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t) --> x="lua-5.1.tar.gz" ``` **Parameters** - `s` (string) - `pattern` (string) - `repl` (string) - `n` (number) (optional) ### string.len *Type:* FUNCTION Receives a string and returns its length. The empty string "" has length 0. Embedded zeros are counted, so "a\000bc\000" has length 5. **Parameters** - `s` (string) ### string.lower *Type:* FUNCTION Receives a string and returns a copy of this string with all uppercase letters changed to lowercase. All other characters are left unchanged. The definition of what an uppercase letter is depends on the current locale. **Parameters** - `s` (string) ### string.match *Type:* FUNCTION Looks for the first match of pattern in the string s. If it finds one, then match returns the captures from the pattern; otherwise it returns nil. If pattern specifies no captures, then the whole match is returned. A third, optional numerical argument init specifies where to start the search; its default value is 1 and can be negative. **Parameters** - `s` (string) - `pattern` (string) - `init` (number) (optional) ### string.rep *Type:* FUNCTION Returns a string that is the concatenation of n copies of the string s. **Parameters** - `s` (string) - `n` (number) ### string.reverse *Type:* FUNCTION Returns a string that is the string s reversed. **Parameters** - `s` (string) ### string.sub *Type:* FUNCTION Returns the substring of s that starts at i and continues until j; i and j can be negative. If j is absent, then it is assumed to be equal to -1 (which is the same as the string length). In particular, the call string.sub(s,1,j) returns a prefix of s with length j, and string.sub(s, -i) returns a suffix of s with length i. **Parameters** - `s` (string) - `i` (number) - `j` (number) (optional) ### string.upper *Type:* FUNCTION Receives a string and returns a copy of this string with all lowercase letters changed to uppercase. All other characters are left unchanged. The definition of what a lowercase letter is depends on the current locale. **Parameters** - `s` (string) # System {#apis:sys-lua} **Namespace:** `sys` **Language:** Lua **Type:** Defold Lua **File:** `script_engine.cpp` **Source:** `engine/engine/src/script/script_engine.cpp` Functions and messages for using system resources, controlling the engine, error handling and debugging. ## API ### exit *Type:* MESSAGE Terminates the game application and reports the specified code to the OS. This message can only be sent to the designated @system socket. **Parameters** - `code` (number) - exit code to report to the OS, 0 means clean exit **Examples** This examples demonstrates how to exit the application when some kind of quit messages is received (maybe from gui or similar): ``` function on_message(self, message_id, message, sender) if message_id == hash("quit") then msg.post("@system:", "exit", {code = 0}) end end ``` ### reboot *Type:* MESSAGE Reboots the game engine with a specified set of arguments. Arguments will be translated into command line arguments. Sending the reboot command is equivalent to starting the engine with the same arguments. On startup the engine reads configuration from "game.project" in the project root. This message can only be sent to the designated @system socket. **Parameters** - `arg1` (string) - argument 1 - `arg2` (string) - argument 2 - `arg3` (string) - argument 3 - `arg4` (string) - argument 4 - `arg5` (string) - argument 5 - `arg6` (string) - argument 6 **Examples** How to reboot engine with a specific bootstrap collection. ``` local arg1 = '--config=bootstrap.main_collection=/my.collectionc' local arg2 = 'build/game.projectc' msg.post("@system:", "reboot", {arg1 = arg1, arg2 = arg2}) ``` ### resume_rendering *Type:* MESSAGE Resume rendering. This message can only be sent to the designated @system socket. **Examples** msg.post("@system:", "resume_rendering") ### set_update_frequency *Type:* MESSAGE Set game update-frequency (frame cap). This option is equivalent to display.update_frequency in the "game.project" settings but set in run-time. If Vsync checked in "game.project", the rate will be clamped to a swap interval that matches any detected main monitor refresh rate. If Vsync is unchecked the engine will try to respect the rate in software using timers. There is no guarantee that the frame cap will be achieved depending on platform specifics and hardware settings. This message can only be sent to the designated @system socket. **Parameters** - `frequency` (number) - target frequency. 60 for 60 fps **Examples** msg.post("@system:", "set_update_frequency", { frequency = 60 } ) ### set_vsync *Type:* MESSAGE Set the vsync swap interval. The interval with which to swap the front and back buffers in sync with vertical blanks (v-blank), the hardware event where the screen image is updated with data from the front buffer. A value of 1 swaps the buffers at every v-blank, a value of 2 swaps the buffers every other v-blank and so on. A value of 0 disables waiting for v-blank before swapping the buffers. Default value is 1. When setting the swap interval to 0 and having vsync disabled in "game.project", the engine will try to respect the set frame cap value from "game.project" in software instead. This setting may be overridden by driver settings. This message can only be sent to the designated @system socket. **Parameters** - `swap_interval` (number) - target swap interval. **Examples** msg.post("@system:", "set_vsync", { swap_interval = 1 } ) ### start_record *Type:* MESSAGE Starts video recording of the game frame-buffer to file. Current video format is the open vp8 codec in the ivf container. It's possible to upload this format directly to YouTube. The VLC video player has native support but with the known issue that not the entire file is played back. It's probably an issue with VLC. The Miro Video Converter has support for vp8/ivf. Video recording is only supported on desktop platforms. Audio is currently not supported Window width and height must be a multiple of 8 to be able to record video. This message can only be sent to the designated @system socket. **Parameters** - `file_name` (string) - file name to write the video to - `frame_period` (number) - frame period to record, ie write every nth frame. Default value is 2 - `fps` (number) - frames per second. Playback speed for the video. Default value is 30. The fps value doens't affect the recording. It's only meta-data in the written video file. **Examples** Record a video in 30 fps given that the native game fps is 60: ``` msg.post("@system:", "start_record", { file_name = "test_rec.ivf" } ) ``` To write a video in 60 fps given that the native game fps is 60: ``` msg.post("@system:", "start_record", { file_name = "test_rec.ivf", frame_period = 1, fps = 60 } ) ``` ### stop_record *Type:* MESSAGE Stops the currently active video recording. Video recording is only supported on desktop platforms. This message can only be sent to the designated @system socket. **Examples** ``` msg.post("@system:", "stop_record") ``` ### sys.deserialize *Type:* FUNCTION This function will raise a Lua error if an error occurs while deserializing the buffer. **Parameters** - `buffer` (string) - buffer to deserialize from **Returns** - `table` (table) - lua table with deserialized data **Examples** Deserialize a lua table that was previously serialized: ``` local buffer = sys.serialize(my_table) local table = sys.deserialize(buffer) ``` ### sys.exists *Type:* FUNCTION Check if a path exists Good for checking if a file exists before loading a large file **Parameters** - `path` (string) - path to check **Returns** - `result` (boolean) - true if the path exists, false otherwise **Examples** Load data but return nil if path didn't exist ``` if not sys.exists(path) then return nil end return sys.load(path) -- returns {} if it failed ``` ### sys.exit *Type:* FUNCTION Terminates the game application and reports the specified code to the OS. **Parameters** - `code` (number) - exit code to report to the OS, 0 means clean exit **Examples** This examples demonstrates how to exit the application when some kind of quit messages is received (maybe from gui or similar): ``` function on_message(self, message_id, message, sender) if message_id == hash("quit") then sys.exit(0) end end ``` ### sys.get_application_info *Type:* FUNCTION Returns a table with application information for the requested app. On iOS, the app_string is an url scheme for the app that is queried. Your game needs to list the schemes that are queried in an LSApplicationQueriesSchemes array in a custom "Info.plist". On Android, the app_string is the package identifier for the app. **Parameters** - `app_string` (string) - platform specific string with application package or query, see above for details. **Returns** - `app_info` (table) - table with application information in the following fields:
installed
boolean true if the application is installed, false otherwise.
**Examples** Check if twitter is installed: ``` sysinfo = sys.get_sys_info() twitter = {} if sysinfo.system_name == "Android" then twitter = sys.get_application_info("com.twitter.android") elseif sysinfo.system_name == "iPhone OS" then twitter = sys.get_application_info("twitter:") end if twitter.installed then -- twitter is installed! end ``` Info.plist for the iOS app needs to list the schemes that are queried: ``` ... LSApplicationQueriesSchemes twitter ... ``` ### sys.get_application_path *Type:* FUNCTION The path from which the application is run. This function will raise a Lua error if unable to get the application support path. **Returns** - `path` (string) - path to application executable **Examples** Find a path where we can store data (the example path is on the macOS platform): ``` -- macOS: /Applications/my_game.app local application_path = sys.get_application_path() print(application_path) --> /Applications/my_game.app -- Windows: C:\Program Files\my_game\my_game.exe print(application_path) --> C:\Program Files\my_game -- Linux: /home/foobar/my_game/my_game print(application_path) --> /home/foobar/my_game -- Android package name: com.foobar.my_game print(application_path) --> /data/user/0/com.foobar.my_game -- iOS: my_game.app print(application_path) --> /var/containers/Bundle/Applications/123456AB-78CD-90DE-12345678ABCD/my_game.app -- HTML5: http://www.foobar.com/my_game/ print(application_path) --> http://www.foobar.com/my_game ``` ### sys.get_config_boolean *Type:* FUNCTION Get boolean config value from the game.project configuration file with optional default value **Parameters** - `key` (string) - key to get value for. The syntax is SECTION.KEY - `default_value` (boolean) (optional) - (optional) default value to return if the value does not exist **Returns** - `value` (boolean) - config value as a boolean. default_value if the config key does not exist. false if no default value was supplied. **Examples** Get user config value ``` local vsync = sys.get_config_boolean("display.vsync", false) ``` ### sys.get_config_int *Type:* FUNCTION Get integer config value from the game.project configuration file with optional default value **Parameters** - `key` (string) - key to get value for. The syntax is SECTION.KEY - `default_value` (number) (optional) - (optional) default value to return if the value does not exist **Returns** - `value` (number) - config value as an integer. default_value if the config key does not exist. 0 if no default value was supplied. **Examples** Get user config value ``` local speed = sys.get_config_int("my_game.speed", 20) -- with default value ``` ``` local testmode = sys.get_config_int("my_game.testmode") -- without default value if testmode ~= nil then -- do stuff end ``` ### sys.get_config_number *Type:* FUNCTION Get number config value from the game.project configuration file with optional default value **Parameters** - `key` (string) - key to get value for. The syntax is SECTION.KEY - `default_value` (number) (optional) - (optional) default value to return if the value does not exist **Returns** - `value` (number) - config value as an number. default_value if the config key does not exist. 0 if no default value was supplied. **Examples** Get user config value ``` local speed = sys.get_config_number("my_game.speed", 20.0) ``` ### sys.get_config_string *Type:* FUNCTION Get string config value from the game.project configuration file with optional default value **Parameters** - `key` (string) - key to get value for. The syntax is SECTION.KEY - `default_value` (string) (optional) - (optional) default value to return if the value does not exist **Returns** - `value` (string) - config value as a string. default_value if the config key does not exist. nil if no default value was supplied. **Examples** Get user config value ``` local text = sys.get_config_string("my_game.text", "default text")) ``` Start the engine with a bootstrap config override and add a custom config value ``` $ dmengine --config=bootstrap.main_collection=/mytest.collectionc --config=mygame.testmode=1 ``` Read the custom config value from the command line ``` local testmode = sys.get_config_int("mygame.testmode") ``` ### sys.get_connectivity *Type:* FUNCTION Returns the current network connectivity status on mobile platforms. On desktop, this function always return sys.NETWORK_CONNECTED. **Returns** - `status` (constant) - network connectivity status:
  • sys.NETWORK_DISCONNECTED (no network connection is found)
  • sys.NETWORK_CONNECTED_CELLULAR (connected through mobile cellular)
  • sys.NETWORK_CONNECTED (otherwise, Wifi)
**Examples** Check if we are connected through a cellular connection ``` if (sys.NETWORK_CONNECTED_CELLULAR == sys.get_connectivity()) then print("Connected via cellular, avoid downloading big files!") end ``` ### sys.get_engine_info *Type:* FUNCTION Returns a table with engine information. **Returns** - `engine_info` (table) - table with engine information in the following fields:
version
string The current Defold engine version, i.e. "1.2.96"
version_sha1
string The SHA1 for the current engine build, i.e. "0060183cce2e29dbd09c85ece83cbb72068ee050"
is_debug
boolean If the engine is a debug or release version
**Examples** How to retrieve engine information: ``` -- Update version text label so our testers know what version we're running local engine_info = sys.get_engine_info() local version_str = "Defold " .. engine_info.version .. "\n" .. engine_info.version_sha1 gui.set_text(gui.get_node("version"), version_str) ``` ### sys.get_host_path *Type:* FUNCTION Create a path to the host device for unit testing Useful for saving logs etc during development **Notes** - Only enabled in debug builds. In release builds returns the string unchanged **Parameters** - `filename` (string) - file to read from **Returns** - `host_path` (string) - the path prefixed with the proper host mount **Examples** Save data on the host ``` local host_path = sys.get_host_path("logs/test.txt") sys.save(host_path, mytable) ``` Load data from the host ``` local host_path = sys.get_host_path("logs/test.txt") local table = sys.load(host_path) ``` ### sys.get_ifaddrs *Type:* FUNCTION Returns an array of tables with information on network interfaces. **Returns** - `ifaddrs` (table) - an array of tables. Each table entry contain the following fields:
name
string Interface name
address
string IP address. might be nil if not available.
mac
string Hardware MAC address. might be nil if not available.
up
boolean true if the interface is up (available to transmit and receive data), false otherwise.
running
boolean true if the interface is running, false otherwise.
**Examples** How to get the IP address of interface "en0": ``` ifaddrs = sys.get_ifaddrs() for _,interface in ipairs(ifaddrs) do if interface.name == "en0" then local ip = interface.address end end ``` ### sys.get_save_file *Type:* FUNCTION The save-file path is operating system specific and is typically located under the user's home directory. This function will raise a Lua error if unable to get the save file path. **Notes** - Setting the environment variable `DM_SAVE_HOME` overrides the default application support path. **Parameters** - `application_id` (string) - user defined id of the application, which helps define the location of the save-file - `file_name` (string) - file-name to get path for **Returns** - `path` (string) - path to save-file **Examples** Find a path where we can store data: ``` local my_file_path = sys.get_save_file("my_game", "my_file") -- macOS: /Users/foobar/Library/Application Support/my_game/my_file print(my_file_path) --> /Users/foobar/Library/Application Support/my_game/my_file -- Windows: C:\Users\foobar\AppData\Roaming\my_game\my_file print(my_file_path) --> C:\Users\foobar\AppData\Roaming\my_game\my_file -- Linux: $XDG_DATA_HOME/my_game/my_file or /home/foobar/.my_game/my_file -- Linux: Defaults to /home/foobar/.local/share/my_game/my_file if neither exist. print(my_file_path) --> /home/foobar/.local/share/my_game/my_file -- Android package name: com.foobar.packagename print(my_file_path) --> /data/data/0/com.foobar.packagename/files/my_file -- iOS: my_game.app print(my_file_path) --> /var/mobile/Containers/Data/Application/123456AB-78CD-90DE-12345678ABCD/my_game/my_file -- HTML5 path inside the IndexedDB: /data/.my_game/my_file or /.my_game/my_file print(my_file_path) --> /data/.my_game/my_file ``` ### sys.get_sys_info *Type:* FUNCTION Returns a table with system information. **Parameters** - `options` (table) (optional) - optional options table - ignore_secure boolean this flag ignores values might be secured by OS e.g. device_ident **Returns** - `sys_info` (table) - table with system information in the following fields:
device_model
string Only available on iOS and Android.
manufacturer
string Only available on iOS and Android.
system_name
string The system name: "Darwin", "Linux", "Windows", "HTML5", "Android" or "iPhone OS"
system_version
string The system OS version.
api_version
string The API version on the system.
language
string Two character ISO-639 format, i.e. "en".
device_language
string Two character ISO-639 format (i.e. "sr") and, if applicable, followed by a dash (-) and an ISO 15924 script code (i.e. "sr-Cyrl" or "sr-Latn"). Reflects the device preferred language.
territory
string Two character ISO-3166 format, i.e. "US".
gmt_offset
number The current offset from GMT (Greenwich Mean Time), in minutes.
device_ident
string This value secured by OS. "identifierForVendor" on iOS. "android_id" on Android. On Android, you need to add READ_PHONE_STATE permission to be able to get this data. We don't use this permission in Defold.
user_agent
string The HTTP user agent, i.e. "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/602.4.8 (KHTML, like Gecko) Version/10.0.3 Safari/602.4.8"
**Examples** How to get system information: ``` local info = sys.get_sys_info() if info.system_name == "HTML5" then -- We are running in a browser. end ``` ### sys.load *Type:* FUNCTION If the file exists, it must have been created by sys.save to be loaded. This function will raise a Lua error if an error occurs while loading the file. **Parameters** - `filename` (string) - file to read from **Returns** - `loaded` (table) - lua table, which is empty if the file could not be found **Examples** Load data that was previously saved, e.g. an earlier game session: ``` local my_file_path = sys.get_save_file("my_game", "my_file") local my_table = sys.load(my_file_path) if not next(my_table) then -- empty table end ``` ### sys.load_buffer *Type:* FUNCTION The sys.load_buffer function will first try to load the resource from any of the mounted resource locations and return the data if any matching entries found. If not, the path will be tried as is from the primary disk on the device. In order for the engine to include custom resources in the build process, you need to specify them in the "custom_resources" key in your "game.project" settings file. You can specify single resource files or directories. If a directory is included in the resource list, all files and directories in that directory is recursively included: For example "main/data/,assets/level_data.json". **Parameters** - `path` (string) - the path to load the buffer from **Returns** - `buffer` (buffer) - the buffer with data **Examples** Load binary data from a custom project resource: ``` local my_buffer = sys.load_buffer("/assets/my_level_data.bin") local data_str = buffer.get_bytes(my_buffer, "data") local has_my_header = string.sub(data_str,1,6) == "D3F0LD" ``` Load binary data from non-custom resource files on disk: ``` local asset_1 = sys.load_buffer("folder_next_to_binary/my_level_asset.txt") local asset_2 = sys.load_buffer("/my/absolute/path") ``` ### sys.load_buffer_async *Type:* FUNCTION The sys.load_buffer function will first try to load the resource from any of the mounted resource locations and return the data if any matching entries found. If not, the path will be tried as is from the primary disk on the device. In order for the engine to include custom resources in the build process, you need to specify them in the "custom_resources" key in your "game.project" settings file. You can specify single resource files or directories. If a directory is included in the resource list, all files and directories in that directory is recursively included: For example "main/data/,assets/level_data.json". Note that issuing multiple requests of the same resource will yield individual buffers per request. There is no implic caching of the buffers based on request path. **Parameters** - `path` (string) - the path to load the buffer from - `status_callback` (function(self, request_id, result)) - A status callback that will be invoked when a request has been handled, or an error occured. The result is a table containing:
status
number The status of the request, supported values are:
  • resource.REQUEST_STATUS_FINISHED
  • resource.REQUEST_STATUS_ERROR_IO_ERROR
  • resource.REQUEST_STATUS_ERROR_NOT_FOUND
buffer
buffer If the request was successfull, this will contain the request payload in a buffer object, and nil otherwise. Make sure to check the status before doing anything with the buffer value!
**Returns** - `handle` (number) - a handle to the request **Examples** Load binary data from a custom project resource and update a texture resource: ``` function my_callback(self, request_id, result) if result.status == resource.REQUEST_STATUS_FINISHED then resource.set_texture("/my_texture", { ... }, result.buf) end end local my_request = sys.load_buffer_async("/assets/my_level_data.bin", my_callback) ``` Load binary data from non-custom resource files on disk: ``` function my_callback(self, request_id, result) if result.status ~= sys.REQUEST_STATUS_FINISHED then -- uh oh! File could not be found, do something graceful elseif request_id == self.first_asset then -- result.buffer contains data from my_level_asset.bin elif request_id == self.second_asset then -- result.buffer contains data from 'my_level.bin' end end function init(self) self.first_asset = hash("folder_next_to_binary/my_level_asset.bin") self.second_asset = hash("/some_absolute_path/my_level.bin") self.first_request = sys.load_buffer_async(self.first_asset, my_callback) self.second_request = sys.load_buffer_async(self.second_asset, my_callback) end ``` ### sys.load_resource *Type:* FUNCTION Loads a custom resource. Specify the full filename of the resource that you want to load. When loaded, the file data is returned as a string. If loading fails, the function returns nil plus the error message. In order for the engine to include custom resources in the build process, you need to specify them in the "custom_resources" key in your "game.project" settings file. You can specify single resource files or directories. If a directory is included in the resource list, all files and directories in that directory is recursively included: For example "main/data/,assets/level_data.json". **Parameters** - `filename` (string) - resource to load, full path **Returns** - `data` (string | nil) - loaded data, or nil if the resource could not be loaded - `error` (string | nil) - the error message, or nil if no error occurred **Examples** ``` -- Load level data into a string local data, error = sys.load_resource("/assets/level_data.json") -- Decode json string to a Lua table if data then local data_table = json.decode(data) pprint(data_table) else print(error) end ``` ### sys.NETWORK_CONNECTED *Type:* CONSTANT network connected through other, non cellular, connection ### sys.NETWORK_CONNECTED_CELLULAR *Type:* CONSTANT network connected through mobile cellular ### sys.NETWORK_DISCONNECTED *Type:* CONSTANT no network connection found ### sys.open_url *Type:* FUNCTION Open URL in default application, typically a browser **Parameters** - `url` (string) - url to open - `attributes` (table) (optional) - table with attributes target - string : Optional. Specifies the target attribute or the name of the window. The following values are supported: - _self - (default value) URL replaces the current page. - _blank - URL is loaded into a new window, or tab. - _parent - URL is loaded into the parent frame. - _top - URL replaces any framesets that may be loaded. - name - The name of the window (Note: the name does not specify the title of the new window). **Returns** - `success` (boolean) - a boolean indicating if the url could be opened or not **Examples** Open an URL: ``` local success = sys.open_url("http://www.defold.com", {target = "_blank"}) if not success then -- could not open the url... end ``` ### sys.reboot *Type:* FUNCTION Reboots the game engine with a specified set of arguments. Arguments will be translated into command line arguments. Calling reboot function is equivalent to starting the engine with the same arguments. On startup the engine reads configuration from "game.project" in the project root. **Parameters** - `arg1` (string) (optional) - argument 1 - `arg2` (string) (optional) - argument 2 - `arg3` (string) (optional) - argument 3 - `arg4` (string) (optional) - argument 4 - `arg5` (string) (optional) - argument 5 - `arg6` (string) (optional) - argument 6 **Examples** How to reboot engine with a specific bootstrap collection. ``` local arg1 = '--config=bootstrap.main_collection=/my.collectionc' local arg2 = 'build/game.projectc' sys.reboot(arg1, arg2) ``` ### sys.REQUEST_STATUS_ERROR_IO_ERROR *Type:* CONSTANT an asyncronous request is unable to read the resource ### sys.REQUEST_STATUS_ERROR_NOT_FOUND *Type:* CONSTANT an asyncronous request is unable to locate the resource ### sys.REQUEST_STATUS_FINISHED *Type:* CONSTANT an asyncronous request has finished successfully ### sys.save *Type:* FUNCTION The table can later be loaded by sys.load. Use sys.get_save_file to obtain a valid location for the file. Internally, this function uses a workspace buffer sized output file sized 512kb. This size reflects the output file size which must not exceed this limit. Additionally, the total number of rows that any one table may contain is limited to 65536 (i.e. a 16 bit range). When tables are used to represent arrays, the values of keys are permitted to fall within a 32 bit range, supporting sparse arrays, however the limit on the total number of rows remains in effect. This function will raise a Lua error if an error occurs while saving the table. **Parameters** - `filename` (string) - file to write to - `table` (table) - lua table to save **Examples** Save data: ``` local my_table = {} table.insert(my_table, "my_value") local my_file_path = sys.get_save_file("my_game", "my_file") sys.save(my_file_path, my_table) ``` ### sys.serialize *Type:* FUNCTION The buffer can later deserialized by sys.deserialize. This function has all the same limitations as sys.save. This function will raise a Lua error if an error occurs while serializing the table. **Parameters** - `table` (table) - lua table to serialize **Returns** - `buffer` (string) - serialized data buffer **Examples** Serialize table: ``` local my_table = {} table.insert(my_table, "my_value") local buffer = sys.serialize(my_table) ``` ### sys.set_connectivity_host *Type:* FUNCTION Sets the host that is used to check for network connectivity against. **Parameters** - `host` (string) - hostname to check against **Examples** ``` sys.set_connectivity_host("www.google.com") ``` ### sys.set_engine_throttle *Type:* FUNCTION Enables engine throttling. **Notes** - It will automatically wake up on input events - It will automatically throttle again after the cooldown period - It skips entire update+render loop on the main thread. E.g loading of assets, callbacks from threads (http) - On threaded systems, Sound will continue to play any started non-streaming sounds. (e.g. looping background music) **Parameters** - `enable` (boolean) - true if throttling should be enabled - `cooldown` (number) - the time period to do update + render for (seconds) **Examples** Disable throttling ``` sys.set_engine_throttle(false) ``` Enable throttling ``` sys.set_engine_throttle(true, 1.5) ``` ### sys.set_error_handler *Type:* FUNCTION Set the Lua error handler function. The error handler is a function which is called whenever a lua runtime error occurs. **Parameters** - `error_handler` (function(source, message, traceback)) - the function to be called on error
source
string The runtime context of the error. Currently, this is always "lua".
message
string The source file, line number and error message.
traceback
string The stack traceback.
**Examples** Install error handler that just prints the errors ``` local function my_error_handler(source, message, traceback) print(source) --> lua print(message) --> main/my.script:10: attempt to perform arithmetic on a string value print(traceback) --> stack traceback: --> main/test.script:10: in function 'boom' --> main/test.script:15: in function end local function boom() return 10 + "string" end function init(self) sys.set_error_handler(my_error_handler) boom() end ``` ### sys.set_render_enable *Type:* FUNCTION Disables rendering **Notes** - It will will leave the back buffer as-is **Parameters** - `enable` (boolean) - true if throttling should be enabled **Examples** Disable rendering ``` sys.set_render_enable(false) ``` ### sys.set_update_frequency *Type:* FUNCTION Set game update-frequency (frame cap). This option is equivalent to display.update_frequency in the "game.project" settings but set in run-time. If Vsync checked in "game.project", the rate will be clamped to a swap interval that matches any detected main monitor refresh rate. If Vsync is unchecked the engine will try to respect the rate in software using timers. There is no guarantee that the frame cap will be achieved depending on platform specifics and hardware settings. **Parameters** - `frequency` (number) - target frequency. 60 for 60 fps **Examples** Setting the update frequency to 60 frames per second ``` sys.set_update_frequency(60) ``` ### sys.set_vsync_swap_interval *Type:* FUNCTION Set the vsync swap interval. The interval with which to swap the front and back buffers in sync with vertical blanks (v-blank), the hardware event where the screen image is updated with data from the front buffer. A value of 1 swaps the buffers at every v-blank, a value of 2 swaps the buffers every other v-blank and so on. A value of 0 disables waiting for v-blank before swapping the buffers. Default value is 1. When setting the swap interval to 0 and having vsync disabled in "game.project", the engine will try to respect the set frame cap value from "game.project" in software instead. This setting may be overridden by driver settings. **Parameters** - `swap_interval` (number) - target swap interval. **Examples** Setting the swap intervall to swap every v-blank ``` sys.set_vsync_swap_interval(1) ``` ### toggle_physics_debug *Type:* MESSAGE Toggles the on-screen physics visual debugging mode which is very useful for tracking down issues related to physics. This mode visualizes all collision object shapes and normals at detected contact points. Toggling this mode on is equal to setting physics.debug in the "game.project" settings, but set in run-time. This message can only be sent to the designated @system socket. **Examples** ``` msg.post("@system:", "toggle_physics_debug") ``` ### toggle_profile *Type:* MESSAGE Toggles the on-screen profiler. The profiler is a real-time tool that shows the numbers of milliseconds spent in each scope per frame as well as counters. The profiler is very useful for tracking down performance and resource problems. In addition to the on-screen profiler, Defold includes a web-based profiler that allows you to sample a series of data points and then analyze them in detail. The web profiler is available at http://:8002 where is the IP address of the device you are running your game on. This message can only be sent to the designated @system socket. **Examples** ``` msg.post("@system:", "toggle_profile") ``` # Table {#apis:table-lua} **Namespace:** `table` **Language:** Lua **Type:** Defold Lua **File:** `lua_table.doc_h` **Source:** `engine/lua/src/lua_table.doc_h` Documentation for the Lua table standard library. From [Lua 5.1 Reference Manual](https://www.lua.org/manual/5.1/) by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes. Copyright © 2006-2012 Lua.org, PUC-Rio. Freely available under the terms of the [Lua license](https://www.lua.org/license.html). ## API ### table.concat *Type:* FUNCTION Given an array where all elements are strings or numbers, returns table[i]..sep..table[i+1] ... sep..table[j]. The default value for sep is the empty string, the default for i is 1, and the default for j is the length of the table. If i is greater than j, returns the empty string. **Parameters** - `table` (table) - `sep` (string) (optional) - `i` (number) (optional) - `j` (number) (optional) ### table.insert *Type:* FUNCTION Inserts element value at position pos in table, shifting up other elements to open space, if necessary. The default value for pos is n+1, where n is the length of the table , so that a call table.insert(t,x) inserts x at the end of table t. **Parameters** - `table` (table) - `pos` (number) (optional) - `value` (any) ### table.maxn *Type:* FUNCTION Returns the largest positive numerical index of the given table, or zero if the table has no positive numerical indices. (To do its job this function does a linear traversal of the whole table.) **Parameters** - `table` (table) ### table.remove *Type:* FUNCTION Removes from table the element at position pos, shifting down other elements to close the space, if necessary. Returns the value of the removed element. The default value for pos is n, where n is the length of the table, so that a call table.remove(t) removes the last element of table t. **Parameters** - `table` (table) - `pos` (number) (optional) ### table.sort *Type:* FUNCTION Sorts table elements in a given order, in-place, from table[1] to table[n], where n is the length of the table. If comp is given, then it must be a function that receives two table elements, and returns true when the first is less than the second (so that not comp(a[i+1],a[i]) will be true after the sort). If comp is not given, then the standard Lua operator is used instead. The sort algorithm is not stable; that is, elements considered equal by the given order may have their relative positions changed by the sort. **Parameters** - `table` (table) - `comp` (function) (optional) # Tilemap {#apis:tilemap-lua} **Namespace:** `tilemap` **Language:** Lua **Type:** Defold Lua **File:** `script_tilemap.cpp` **Source:** `engine/gamesys/src/gamesys/scripts/script_tilemap.cpp` Functions and messages used to manipulate tile map components. ## API ### material *Type:* PROPERTY The material used when rendering the tile map. The type of the property is hash. **Examples** How to set material using a script property (see resource.material) ``` go.property("my_material", resource.material("/material.material")) function init(self) go.set("#tilemap", "material", self.my_material) end ``` ### tile_source *Type:* PROPERTY The tile source used when rendering the tile map. The type of the property is hash. **Examples** How to set tile source using a script property (see resource.tile_source) ``` go.property("my_tile_source", resource.tile_source("/tilesource.tilesource")) function init(self) go.set("#tilemap", "tile_source", self.my_tile_source) end ``` ### tilemap.get_bounds *Type:* FUNCTION Get the bounds for a tile map. This function returns multiple values: The lower left corner index x and y coordinates (1-indexed), the tile map width and the tile map height. The resulting values take all tile map layers into account, meaning that the bounds are calculated as if all layers were collapsed into one. **Parameters** - `url` (string | hash | url) - the tile map **Returns** - `x` (number) - x coordinate of the bottom left corner - `y` (number) - y coordinate of the bottom left corner - `w` (number) - number of columns (width) in the tile map - `h` (number) - number of rows (height) in the tile map **Examples** ``` -- get the level bounds. local x, y, w, h = tilemap.get_bounds("/level#tilemap") ``` ### tilemap.get_tile *Type:* FUNCTION Get the tile set at the specified position in the tilemap. The position is identified by the tile index starting at origin with index 1, 1. (see tilemap.set_tile()) Which tile map and layer to query is identified by the URL and the layer name parameters. **Parameters** - `url` (string | hash | url) - the tile map - `layer` (string | hash) - name of the layer for the tile - `x` (number) - x-coordinate of the tile - `y` (number) - y-coordinate of the tile **Returns** - `tile` (number) - index of the tile **Examples** ``` -- get the tile under the player. local tileno = tilemap.get_tile("/level#tilemap", "foreground", self.player_x, self.player_y) ``` ### tilemap.get_tile_info *Type:* FUNCTION Get the tile information at the specified position in the tilemap. The position is identified by the tile index starting at origin with index 1, 1. (see tilemap.set_tile()) Which tile map and layer to query is identified by the URL and the layer name parameters. **Parameters** - `url` (string | hash | url) - the tile map - `layer` (string | hash) - name of the layer for the tile - `x` (number) - x-coordinate of the tile - `y` (number) - y-coordinate of the tile **Returns** - `tile_info` (table) - index of the tile **Examples** ``` -- get the tile under the player. local tile_info = tilemap.get_tile_info("/level#tilemap", "foreground", self.player_x, self.player_y) pprint(tile_info) -- { -- index = 0, -- h_flip = false, -- v_flip = true, -- rotate_90 = false -- } ``` ### tilemap.get_tiles *Type:* FUNCTION Retrieves all the tiles for the specified layer in the tilemap. It returns a table of rows where the keys are the tile positions (see tilemap.get_bounds()). You can iterate it using tiles[row_index][column_index]. **Parameters** - `url` (string | hash | url) - the tilemap - `layer` (string | hash) - the name of the layer for the tiles **Returns** - `tiles` (table) - a table of rows representing the layer **Examples** ``` local left, bottom, columns_count, rows_count = tilemap.get_bounds("#tilemap") local tiles = tilemap.get_tiles("#tilemap", "layer") local tile, count = 0, 0 for row_index = bottom, bottom + rows_count - 1 do for column_index = left, left + columns_count - 1 do tile = tiles[row_index][column_index] count = count + 1 end end ``` ### tilemap.H_FLIP *Type:* CONSTANT flip tile horizontally ### tilemap.ROTATE_180 *Type:* CONSTANT rotate tile 180 degrees clockwise ### tilemap.ROTATE_270 *Type:* CONSTANT rotate tile 270 degrees clockwise ### tilemap.ROTATE_90 *Type:* CONSTANT rotate tile 90 degrees clockwise ### tilemap.set_tile *Type:* FUNCTION Replace a tile in a tile map with a new tile. The coordinates of the tiles are indexed so that the "first" tile just above and to the right of origin has coordinates 1,1. Tiles to the left of and below origin are indexed 0, -1, -2 and so forth. +-------+-------+------+------+ | 0,3 | 1,3 | 2,3 | 3,3 | +-------+-------+------+------+ | 0,2 | 1,2 | 2,2 | 3,2 | +-------+-------+------+------+ | 0,1 | 1,1 | 2,1 | 3,1 | +-------O-------+------+------+ | 0,0 | 1,0 | 2,0 | 3,0 | +-------+-------+------+------+ The coordinates must be within the bounds of the tile map as it were created. That is, it is not possible to extend the size of a tile map by setting tiles outside the edges. To clear a tile, set the tile to number 0. Which tile map and layer to manipulate is identified by the URL and the layer name parameters. Transform bitmask is arithmetic sum of one or both FLIP constants (tilemap.H_FLIP, tilemap.V_FLIP) and/or one of ROTATION constants (tilemap.ROTATE_90, tilemap.ROTATE_180, tilemap.ROTATE_270). Flip always applies before rotation (clockwise). **Parameters** - `url` (string | hash | url) - the tile map - `layer` (string | hash) - name of the layer for the tile - `x` (number) - x-coordinate of the tile - `y` (number) - y-coordinate of the tile - `tile` (number) - index of new tile to set. 0 resets the cell - `transform_bitmask` (number) (optional) - optional flip and/or rotation should be applied to the tile **Examples** ``` -- Clear the tile under the player. tilemap.set_tile("/level#tilemap", "foreground", self.player_x, self.player_y, 0) -- Set tile with different combination of flip and rotation tilemap.set_tile("#tilemap", "layer1", x, y, 0, tilemap.H_FLIP + tilemap.V_FLIP + tilemap.ROTATE_90) tilemap.set_tile("#tilemap", "layer1", x, y, 0, tilemap.H_FLIP + tilemap.ROTATE_270) tilemap.set_tile("#tilemap", "layer1", x, y, 0, tilemap.V_FLIP + tilemap.H_FLIP) tilemap.set_tile("#tilemap", "layer1", x, y, 0, tilemap.ROTATE_180) ``` ### tilemap.set_visible *Type:* FUNCTION Sets the visibility of the tilemap layer **Parameters** - `url` (string | hash | url) - the tile map - `layer` (string | hash) - name of the layer for the tile - `visible` (boolean) - should the layer be visible **Examples** ``` -- Disable rendering of the layer tilemap.set_visible("/level#tilemap", "foreground", false) ``` ### tilemap.V_FLIP *Type:* CONSTANT flip tile vertically # Timer {#apis:timer-lua} **Namespace:** `timer` **Language:** Lua **Type:** Defold Lua **File:** `script_timer.cpp` **Source:** `engine/script/src/script_timer.cpp` Timers allow you to set a delay and a callback to be called when the timer completes. The timers created with this API are updated with the collection timer where they are created. If you pause or speed up the collection (using `set_time_step`) it will also affect the new timer. ## API ### timer.cancel *Type:* FUNCTION You may cancel a timer from inside a timer callback. Cancelling a timer that is already executed or cancelled is safe. **Parameters** - `handle` (number) - the timer handle returned by timer.delay() **Returns** - `true` (boolean) - if the timer was active, false if the timer is already cancelled / complete **Examples** ``` self.handle = timer.delay(1, true, function() print("print every second") end) ... local result = timer.cancel(self.handle) if not result then print("the timer is already cancelled") end ``` ### timer.delay *Type:* FUNCTION Adds a timer and returns a unique handle. You may create more timers from inside a timer callback. Using a delay of 0 will result in a timer that triggers at the next frame just before script update functions. If you want a timer that triggers on each frame, set delay to 0.0f and repeat to true. Timers created within a script will automatically die when the script is deleted. **Parameters** - `delay` (number) - time interval in seconds - `repeating` (boolean) - true = repeat timer until cancel, false = one-shot timer - `callback` (function(self, handle, time_elapsed)) - timer callback function
self
object The current object
handle
number The handle of the timer
time_elapsed
number The elapsed time - on first trigger it is time since timer.delay call, otherwise time since last trigger
**Returns** - `handle` (number) - identifier for the create timer, returns timer.INVALID_TIMER_HANDLE if the timer can not be created **Examples** A simple one-shot timer ``` timer.delay(1, false, function() print("print in one second") end) ``` Repetitive timer which canceled after 10 calls ``` local function call_every_second(self, handle, time_elapsed) self.counter = self.counter + 1 print("Call #", self.counter) if self.counter == 10 then timer.cancel(handle) -- cancel timer after 10 calls end end self.counter = 0 timer.delay(1, true, call_every_second) ``` ### timer.get_info *Type:* FUNCTION Get information about timer. **Parameters** - `handle` (number) - the timer handle returned by timer.delay() **Returns** - `data` (table | nil) - table or nil if timer is cancelled/completed. table with data in the following fields:
time_remaining
number Time remaining until the next time a timer.delay() fires.
delay
number Time interval.
repeating
boolean true = repeat timer until cancel, false = one-shot timer.
**Examples** ``` self.handle = timer.delay(1, true, function() print("print every second") end) ... local result = timer.get_info(self.handle) if not result then print("the timer is already cancelled or complete") else pprint(result) -- delay, time_remaining, repeating end ``` ### timer.INVALID_TIMER_HANDLE *Type:* CONSTANT Indicates an invalid timer handle ### timer.trigger *Type:* FUNCTION Manual triggering a callback for a timer. **Parameters** - `handle` (number) - the timer handle returned by timer.delay() **Returns** - `true` (boolean) - if the timer was active, false if the timer is already cancelled / complete **Examples** ``` self.handle = timer.delay(1, true, function() print("print every second or manually by timer.trigger") end) ... local result = timer.trigger(self.handle) if not result then print("the timer is already cancelled or complete") end ``` # Types {#apis:types-lua} **Namespace:** `types` **Language:** Lua **Type:** Defold Lua **File:** `script_types.cpp` **Source:** `engine/script/src/script_types.cpp` Functions for checking Defold userdata types. ## API ### types.is_hash *Type:* FUNCTION Check if passed type is hash. **Parameters** - `var` (any) - Variable to check type **Returns** - `result` (boolean) - True if passed type is hash ### types.is_matrix4 *Type:* FUNCTION Check if passed type is matrix4. **Parameters** - `var` (any) - Variable to check type **Returns** - `result` (boolean) - True if passed type is matrix4 ### types.is_quat *Type:* FUNCTION Check if passed type is quaternion. **Parameters** - `var` (any) - Variable to check type **Returns** - `result` (boolean) - True if passed type is quaternion ### types.is_url *Type:* FUNCTION Check if passed type is URL. **Parameters** - `var` (any) - Variable to check type **Returns** - `result` (boolean) - True if passed type is URL ### types.is_vector *Type:* FUNCTION Check if passed type is vector. **Notes** - 'vector3' and 'vector4' types is not a 'vector' type under the hood. So if called `types.is_vector(vmath.vector3())` it returns 'false' **Parameters** - `var` (any) - Variable to check type **Returns** - `result` (boolean) - True if passed type is vector ### types.is_vector3 *Type:* FUNCTION Check if passed type is vector3. **Parameters** - `var` (any) - Variable to check type **Returns** - `result` (boolean) - True if passed type is vector3 ### types.is_vector4 *Type:* FUNCTION Check if passed type is vector4. **Parameters** - `var` (any) - Variable to check type **Returns** - `result` (boolean) - True if passed type is vector4 # Vector math {#apis:vmath-lua} **Namespace:** `vmath` **Language:** Lua **Type:** Defold Lua **File:** `script_vmath.cpp` **Source:** `engine/script/src/script_vmath.cpp` Functions for mathematical operations on vectors, matrices and quaternions. - The vector types (`vmath.vector3` and `vmath.vector4`) supports addition and subtraction with vectors of the same type. Vectors can be negated and multiplied (scaled) or divided by numbers. - The quaternion type (`vmath.quat`) supports multiplication with other quaternions. - The matrix type (`vmath.matrix4`) can be multiplied with numbers, other matrices and `vmath.vector4` values. - All types performs equality comparison by each component value. The following components are available for the various types: vector3 : `x`, `y` and `z`. Example: `v.y` vector4 : `x`, `y`, `z`, and `w`. Example: `v.w` quaternion : `x`, `y`, `z`, and `w`. Example: `q.w` matrix4 : `m00` to `m33` where the first number is the row (starting from 0) and the second number is the column. Columns can be accessed with `c0` to `c3`, returning a `vector4`. Example: `m.m21` which is equal to `m.c1.z` vector : indexed by number 1 to the vector length. Example: `v[3]` ## API ### vmath.clamp *Type:* FUNCTION Clamp input value to be in range of [min, max]. In case if input value has vector3|vector4 type return new vector3|vector4 with clamped value at every vector's element. Min/max arguments can be vector3|vector4. In that case clamp excuted per every vector's element **Parameters** - `value` (number | vector3 | vector4) - Input value or vector of values - `min` (number | vector3 | vector4) - Min value(s) border - `max` (number | vector3 | vector4) - Max value(s) border **Returns** - `clamped_value` (number | vector3 | vector4) - Clamped value or vector **Examples** ``` local value1 = 56 print(vmath.clamp(value1, 89, 134)) -> 89 local v2 = vmath.vector3(190, 190, -10) print(vmath.clamp(v2, -50, 150)) -> vmath.vector3(150, 150, -10) local v3 = vmath.vector4(30, -30, 45, 1) print(vmath.clamp(v3, 0, 20)) -> vmath.vector4(20, 0, 20, 1) local min_v = vmath.vector4(0, -10, -10, 1) print(vmath.clamp(v3, min_v, 20)) -> vmath.vector4(20, -10, 20, 1) ``` ### vmath.conj *Type:* FUNCTION Calculates the conjugate of a quaternion. The result is a quaternion with the same magnitudes but with the sign of the imaginary (vector) parts changed: q* = [w, -v] **Parameters** - `q1` (quaternion) - quaternion of which to calculate the conjugate **Returns** - `q` (quaternion) - the conjugate **Examples** ``` local quat = vmath.quat(1, 2, 3, 4) print(vmath.conj(quat)) --> vmath.quat(-1, -2, -3, 4) ``` ### vmath.cross *Type:* FUNCTION Given two linearly independent vectors P and Q, the cross product, P × Q, is a vector that is perpendicular to both P and Q and therefore normal to the plane containing them. If the two vectors have the same direction (or have the exact opposite direction from one another, i.e. are not linearly independent) or if either one has zero length, then their cross product is zero. **Parameters** - `v1` (vector3) - first vector - `v2` (vector3) - second vector **Returns** - `v` (vector3) - a new vector representing the cross product **Examples** ``` local vec1 = vmath.vector3(1, 0, 0) local vec2 = vmath.vector3(0, 1, 0) print(vmath.cross(vec1, vec2)) --> vmath.vector3(0, 0, 1) local vec3 = vmath.vector3(-1, 0, 0) print(vmath.cross(vec1, vec3)) --> vmath.vector3(0, -0, 0) ``` ### vmath.dot *Type:* FUNCTION The returned value is a scalar defined as: P ⋅ Q = |P| |Q| cos θ where θ is the angle between the vectors P and Q. If the dot product is positive then the angle between the vectors is below 90 degrees. If the dot product is zero the vectors are perpendicular (at right-angles to each other). If the dot product is negative then the angle between the vectors is more than 90 degrees. **Parameters** - `v1` (vector3 | vector4) - first vector - `v2` (vector3 | vector4) - second vector **Returns** - `n` (number) - dot product **Examples** ``` if vmath.dot(vector1, vector2) == 0 then -- The two vectors are perpendicular (at right-angles to each other) ... end ``` ### vmath.euler_to_quat *Type:* FUNCTION Converts euler angles (x, y, z) in degrees into a quaternion The error is guaranteed to be less than 0.001. If the first argument is vector3, its values are used as x, y, z angles. **Parameters** - `x` (number | vector3) - rotation around x-axis in degrees or vector3 with euler angles in degrees - `y` (number) - rotation around y-axis in degrees - `z` (number) - rotation around z-axis in degrees **Returns** - `q` (quaternion) - quaternion describing an equivalent rotation (231 (YZX) rotation sequence) **Examples** ``` local q = vmath.euler_to_quat(0, 45, 90) print(q) --> vmath.quat(0.27059805393219, 0.27059805393219, 0.65328145027161, 0.65328145027161) local v = vmath.vector3(0, 0, 90) print(vmath.euler_to_quat(v)) --> vmath.quat(0, 0, 0.70710676908493, 0.70710676908493) ``` ### vmath.inv *Type:* FUNCTION The resulting matrix is the inverse of the supplied matrix. For ortho-normal matrices, e.g. regular object transformation, use vmath.ortho_inv() instead. The specialized inverse for ortho-normalized matrices is much faster than the general inverse. **Parameters** - `m1` (matrix4) - matrix to invert **Returns** - `m` (matrix4) - inverse of the supplied matrix **Examples** ``` local mat1 = vmath.matrix4_rotation_z(3.141592653) local mat2 = vmath.inv(mat1) -- M * inv(M) = identity matrix print(mat1 * mat2) --> vmath.matrix4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) ``` ### vmath.length *Type:* FUNCTION Returns the length of the supplied vector or quaternion. If you are comparing the lengths of vectors or quaternions, you should compare the length squared instead as it is slightly more efficient to calculate (it eliminates a square root calculation). **Parameters** - `v` (vector3 | vector4 | quaternion) - value of which to calculate the length **Returns** - `n` (number) - length **Examples** ``` if vmath.length(self.velocity) < max_velocity then -- The speed (velocity vector) is below max. -- TODO: max_velocity can be expressed as squared -- so we can compare with length_sqr() instead. ... end ``` ### vmath.length_sqr *Type:* FUNCTION Returns the squared length of the supplied vector or quaternion. **Parameters** - `v` (vector3 | vector4 | quaternion) - value of which to calculate the squared length **Returns** - `n` (number) - squared length **Examples** ``` if vmath.length_sqr(vector1) < vmath.length_sqr(vector2) then -- Vector 1 has less magnitude than vector 2 ... end ``` ### vmath.lerp *Type:* FUNCTION Linearly interpolate between two vectors. The function treats the vectors as positions and interpolates between the positions in a straight line. Lerp is useful to describe transitions from one place to another over time. The function does not clamp t between 0 and 1. **Parameters** - `t` (number) - interpolation parameter, 0-1 - `v1` (vector3 | vector4) - vector to lerp from - `v2` (vector3 | vector4) - vector to lerp to **Returns** - `v` (vector3 | vector4) - the lerped vector **Examples** ``` function init(self) self.t = 0 end function update(self, dt) self.t = self.t + dt if self.t <= 1 then local startpos = vmath.vector3(0, 600, 0) local endpos = vmath.vector3(600, 0, 0) local pos = vmath.lerp(self.t, startpos, endpos) go.set_position(pos, "go") end end ``` ### vmath.lerp *Type:* FUNCTION Linearly interpolate between two quaternions. Linear interpolation of rotations are only useful for small rotations. For interpolations of arbitrary rotations, vmath.slerp yields much better results. The function does not clamp t between 0 and 1. **Parameters** - `t` (number) - interpolation parameter, 0-1 - `q1` (quaternion) - quaternion to lerp from - `q2` (quaternion) - quaternion to lerp to **Returns** - `q` (quaternion) - the lerped quaternion **Examples** ``` function init(self) self.t = 0 end function update(self, dt) self.t = self.t + dt if self.t <= 1 then local startrot = vmath.quat_rotation_z(0) local endrot = vmath.quat_rotation_z(3.141592653) local rot = vmath.lerp(self.t, startrot, endrot) go.set_rotation(rot, "go") end end ``` ### vmath.lerp *Type:* FUNCTION Linearly interpolate between two values. Lerp is useful to describe transitions from one value to another over time. The function does not clamp t between 0 and 1. **Parameters** - `t` (number) - interpolation parameter, 0-1 - `n1` (number) - number to lerp from - `n2` (number) - number to lerp to **Returns** - `n` (number) - the lerped number **Examples** ``` function init(self) self.t = 0 end function update(self, dt) self.t = self.t + dt if self.t <= 1 then local startx = 0 local endx = 600 local x = vmath.lerp(self.t, startx, endx) go.set_position(vmath.vector3(x, 100, 0), "go") end end ``` ### vmath.matrix4 *Type:* FUNCTION The resulting identity matrix describes a transform with no translation or rotation. **Returns** - `m` (matrix4) - identity matrix **Examples** ``` local mat = vmath.matrix4() print(mat) --> vmath.matrix4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) -- get column 0: print(mat.c0) --> vmath.vector4(1, 0, 0, 0) -- get the value in row 3 and column 2: print(mat.m32) --> 0 ``` ### vmath.matrix4 *Type:* FUNCTION Creates a new matrix with all components set to the corresponding values from the supplied matrix. I.e. the function creates a copy of the given matrix. **Parameters** - `m1` (matrix4) - existing matrix **Returns** - `m` (matrix4) - matrix which is a copy of the specified matrix **Examples** ``` local mat1 = vmath.matrix4_rotation_x(3.141592653) local mat2 = vmath.matrix4(mat1) if mat1 == mat2 then -- yes, they are equal print(mat2) --> vmath.matrix4(1, 0, 0, 0, 0, -1, 8.7422776573476e-08, 0, 0, -8.7422776573476e-08, -1, 0, 0, 0, 0, 1) end ``` ### vmath.matrix4_axis_angle *Type:* FUNCTION The resulting matrix describes a rotation around the axis by the specified angle. **Parameters** - `v` (vector3) - axis - `angle` (number) - angle in radians **Returns** - `m` (matrix4) - matrix represented by axis and angle **Examples** ``` local vec = vmath.vector4(1, 1, 0, 0) local axis = vmath.vector3(0, 0, 1) -- z-axis local mat = vmath.matrix4_axis_angle(axis, 3.141592653) print(mat * vec) --> vmath.vector4(-0.99999994039536, -1.0000001192093, 0, 0) ``` ### vmath.matrix4_compose *Type:* FUNCTION Creates a new matrix constructed from separate translation vector, roation quaternion and scale vector **Parameters** - `translation` (vector3 | vector4) - translation - `rotation` (quaternion) - rotation - `scale` (vector3) - scale **Returns** - `matrix` (matrix4) - new matrix4 **Examples** ``` local translation = vmath.vector3(103, -95, 14) local quat = vmath.quat(1, 2, 3, 4) local scale = vmath.vector3(1, 0.5, 0.5) local result = vmath.matrix4_compose(translation, quat, scale) print(result) --> vmath.matrix4(-25, -10, 11, 103, 28, -9.5, 2, -95, -10, 10, -4.5, 14, 0, 0, 0, 1) ``` ### vmath.matrix4_frustum *Type:* FUNCTION Constructs a frustum matrix from the given values. The left, right, top and bottom coordinates of the view cone are expressed as distances from the center of the near clipping plane. The near and far coordinates are expressed as distances from the tip of the view frustum cone. **Parameters** - `left` (number) - coordinate for left clipping plane - `right` (number) - coordinate for right clipping plane - `bottom` (number) - coordinate for bottom clipping plane - `top` (number) - coordinate for top clipping plane - `near` (number) - coordinate for near clipping plane - `far` (number) - coordinate for far clipping plane **Returns** - `m` (matrix4) - matrix representing the frustum **Examples** ``` -- Construct a projection frustum with a vertical and horizontal -- FOV of 45 degrees. Useful for rendering a square view. local proj = vmath.matrix4_frustum(-1, 1, -1, 1, 1, 1000) render.set_projection(proj) ``` ### vmath.matrix4_look_at *Type:* FUNCTION The resulting matrix is created from the supplied look-at parameters. This is useful for constructing a view matrix for a camera or rendering in general. **Parameters** - `eye` (vector3) - eye position - `look_at` (vector3) - look-at position - `up` (vector3) - up vector **Returns** - `m` (matrix4) - look-at matrix **Examples** ``` -- Set up a perspective camera at z 100 with 45 degrees (pi/2) FOV -- Aspect ratio 4:3 local eye = vmath.vector3(0, 0, 100) local look_at = vmath.vector3(0, 0, 0) local up = vmath.vector3(0, 1, 0) local view = vmath.matrix4_look_at(eye, look_at, up) render.set_view(view) local proj = vmath.matrix4_perspective(3.141592/2, 4/3, 1, 1000) render.set_projection(proj) ``` ### vmath.matrix4_orthographic *Type:* FUNCTION Creates an orthographic projection matrix. This is useful to construct a projection matrix for a camera or rendering in general. **Parameters** - `left` (number) - coordinate for left clipping plane - `right` (number) - coordinate for right clipping plane - `bottom` (number) - coordinate for bottom clipping plane - `top` (number) - coordinate for top clipping plane - `near` (number) - coordinate for near clipping plane - `far` (number) - coordinate for far clipping plane **Returns** - `m` (matrix4) - orthographic projection matrix **Examples** ``` -- Set up an orthographic projection based on the width and height -- of the game window. local w = render.get_width() local h = render.get_height() local proj = vmath.matrix4_orthographic(- w / 2, w / 2, -h / 2, h / 2, -1000, 1000) render.set_projection(proj) ``` ### vmath.matrix4_perspective *Type:* FUNCTION Creates a perspective projection matrix. This is useful to construct a projection matrix for a camera or rendering in general. **Parameters** - `fov` (number) - angle of the full vertical field of view in radians - `aspect` (number) - aspect ratio - `near` (number) - coordinate for near clipping plane - `far` (number) - coordinate for far clipping plane **Returns** - `m` (matrix4) - perspective projection matrix **Examples** ``` -- Set up a perspective camera at z 100 with 45 degrees (pi/2) FOV -- Aspect ratio 4:3 local eye = vmath.vector3(0, 0, 100) local look_at = vmath.vector3(0, 0, 0) local up = vmath.vector3(0, 1, 0) local view = vmath.matrix4_look_at(eye, look_at, up) render.set_view(view) local proj = vmath.matrix4_perspective(3.141592/2, 4/3, 1, 1000) render.set_projection(proj) ``` ### vmath.matrix4_quat *Type:* FUNCTION The resulting matrix describes the same rotation as the quaternion, but does not have any translation (also like the quaternion). **Parameters** - `q` (quaternion) - quaternion to create matrix from **Returns** - `m` (matrix4) - matrix represented by quaternion **Examples** ``` local vec = vmath.vector4(1, 1, 0, 0) local quat = vmath.quat_rotation_z(3.141592653) local mat = vmath.matrix4_quat(quat) print(mat * vec) --> vmath.matrix4_frustum(-1, 1, -1, 1, 1, 1000) ``` ### vmath.matrix4_rotation_x *Type:* FUNCTION The resulting matrix describes a rotation around the x-axis by the specified angle. **Parameters** - `angle` (number) - angle in radians around x-axis **Returns** - `m` (matrix4) - matrix from rotation around x-axis **Examples** ``` local vec = vmath.vector4(1, 1, 0, 0) local mat = vmath.matrix4_rotation_x(3.141592653) print(mat * vec) --> vmath.vector4(1, -1, -8.7422776573476e-08, 0) ``` ### vmath.matrix4_rotation_y *Type:* FUNCTION The resulting matrix describes a rotation around the y-axis by the specified angle. **Parameters** - `angle` (number) - angle in radians around y-axis **Returns** - `m` (matrix4) - matrix from rotation around y-axis **Examples** ``` local vec = vmath.vector4(1, 1, 0, 0) local mat = vmath.matrix4_rotation_y(3.141592653) print(mat * vec) --> vmath.vector4(-1, 1, 8.7422776573476e-08, 0) ``` ### vmath.matrix4_rotation_z *Type:* FUNCTION The resulting matrix describes a rotation around the z-axis by the specified angle. **Parameters** - `angle` (number) - angle in radians around z-axis **Returns** - `m` (matrix4) - matrix from rotation around z-axis **Examples** ``` local vec = vmath.vector4(1, 1, 0, 0) local mat = vmath.matrix4_rotation_z(3.141592653) print(mat * vec) --> vmath.vector4(-0.99999994039536, -1.0000001192093, 0, 0) ``` ### vmath.matrix4_scale *Type:* FUNCTION Creates a new matrix constructed from scale vector **Parameters** - `scale` (vector3) - scale **Returns** - `matrix` (matrix4) - new matrix4 **Examples** ``` local scale = vmath.vector3(1, 0.5, 0.5) local result = vmath.matrix4_scale(scale) print(result) --> vmath.matrix4(1, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1) ``` ### vmath.matrix4_scale *Type:* FUNCTION creates a new matrix4 from uniform scale **Parameters** - `scale` (number) - scale **Returns** - `matrix` (matrix4) - new matrix4 **Examples** ``` local result = vmath.matrix4_scale(0.5) print(result) --> vmath.matrix4(0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1) ``` ### vmath.matrix4_scale *Type:* FUNCTION Creates a new matrix4 from three scale components **Parameters** - `scale_x` (number) - scale along X axis - `scale_y` (number) - sclae along Y axis - `scale_z` (number) - scale along Z asis **Returns** - `matrix` (matrix4) - new matrix4 **Examples** ``` local result = vmath.matrix4_scale(1, 0.5, 0.5) print(result) --> vmath.matrix4(1, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1) ``` ### vmath.matrix4_translation *Type:* FUNCTION The resulting matrix describes a translation of a point in euclidean space. **Parameters** - `position` (vector3 | vector4) - position vector to create matrix from **Returns** - `m` (matrix4) - matrix from the supplied position vector **Examples** ``` -- Set camera view from custom view and translation matrices local mat_trans = vmath.matrix4_translation(vmath.vector3(0, 10, 100)) local mat_view = vmath.matrix4_rotation_y(-3.141592/4) render.set_view(mat_view * mat_trans) ``` ### vmath.mul_per_elem *Type:* FUNCTION Performs an element wise multiplication between two vectors of the same type The returned value is a vector defined as (e.g. for a vector3): v = vmath.mul_per_elem(a, b) = vmath.vector3(a.x * b.x, a.y * b.y, a.z * b.z) **Parameters** - `v1` (vector3 | vector4) - first vector - `v2` (vector3 | vector4) - second vector **Returns** - `v` (vector3 | vector4) - multiplied vector **Examples** ``` local blend_color = vmath.mul_per_elem(color1, color2) ``` ### vmath.normalize *Type:* FUNCTION Normalizes a vector, i.e. returns a new vector with the same direction as the input vector, but with length 1. The length of the vector must be above 0, otherwise a division-by-zero will occur. **Parameters** - `v1` (vector3 | vector4 | quaternion) - vector to normalize **Returns** - `v` (vector3 | vector4 | quaternion) - new normalized vector **Examples** ``` local vec = vmath.vector3(1, 2, 3) local norm_vec = vmath.normalize(vec) print(norm_vec) --> vmath.vector3(0.26726123690605, 0.5345224738121, 0.80178368091583) print(vmath.length(norm_vec)) --> 0.99999994039536 ``` ### vmath.ortho_inv *Type:* FUNCTION The resulting matrix is the inverse of the supplied matrix. The supplied matrix has to be an ortho-normal matrix, e.g. describe a regular object transformation. For matrices that are not ortho-normal use the general inverse vmath.inv() instead. **Parameters** - `m1` (matrix4) - ortho-normalized matrix to invert **Returns** - `m` (matrix4) - inverse of the supplied matrix **Examples** ``` local mat1 = vmath.matrix4_rotation_z(3.141592653) local mat2 = vmath.ortho_inv(mat1) -- M * inv(M) = identity matrix print(mat1 * mat2) --> vmath.matrix4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) ``` ### vmath.project *Type:* FUNCTION Calculates the extent the projection of the first vector onto the second. The returned value is a scalar p defined as: p = |P| cos θ / |Q| where θ is the angle between the vectors P and Q. **Parameters** - `v1` (vector3) - vector to be projected on the second - `v2` (vector3) - vector onto which the first will be projected, must not have zero length **Returns** - `n` (number) - the projected extent of the first vector onto the second **Examples** ``` local v1 = vmath.vector3(1, 1, 0) local v2 = vmath.vector3(2, 0, 0) print(vmath.project(v1, v2)) --> 0.5 ``` ### vmath.quat *Type:* FUNCTION Creates a new identity quaternion. The identity quaternion is equal to: vmath.quat(0, 0, 0, 1) **Returns** - `q` (quaternion) - new identity quaternion **Examples** ``` local quat = vmath.quat() print(quat) --> vmath.quat(0, 0, 0, 1) print(quat.w) --> 1 ``` ### vmath.quat *Type:* FUNCTION Creates a new quaternion with all components set to the corresponding values from the supplied quaternion. I.e. This function creates a copy of the given quaternion. **Parameters** - `q1` (quaternion) - existing quaternion **Returns** - `q` (quaternion) - new quaternion **Examples** ``` local quat1 = vmath.quat(1, 2, 3, 4) local quat2 = vmath.quat(quat1) if quat1 == quat2 then -- yes, they are equal print(quat2) --> vmath.quat(1, 2, 3, 4) end ``` ### vmath.quat *Type:* FUNCTION Creates a new quaternion with the components set according to the supplied parameter values. **Parameters** - `x` (number) - x coordinate - `y` (number) - y coordinate - `z` (number) - z coordinate - `w` (number) - w coordinate **Returns** - `q` (quaternion) - new quaternion **Examples** ``` local quat = vmath.quat(1, 2, 3, 4) print(quat) --> vmath.quat(1, 2, 3, 4) ``` ### vmath.quat_axis_angle *Type:* FUNCTION The resulting quaternion describes a rotation of angle radians around the axis described by the unit vector v. **Parameters** - `v` (vector3) - axis - `angle` (number) - angle **Returns** - `q` (quaternion) - quaternion representing the axis-angle rotation **Examples** ``` local axis = vmath.vector3(1, 0, 0) local rot = vmath.quat_axis_angle(axis, 3.141592653) local vec = vmath.vector3(1, 1, 0) print(vmath.rotate(rot, vec)) --> vmath.vector3(1, -1, -8.7422776573476e-08) ``` ### vmath.quat_basis *Type:* FUNCTION The resulting quaternion describes the rotation from the identity quaternion (no rotation) to the coordinate system as described by the given x, y and z base unit vectors. **Parameters** - `x` (vector3) - x base vector - `y` (vector3) - y base vector - `z` (vector3) - z base vector **Returns** - `q` (quaternion) - quaternion representing the rotation of the specified base vectors **Examples** ``` -- Axis rotated 90 degrees around z. local rot_x = vmath.vector3(0, -1, 0) local rot_y = vmath.vector3(1, 0, 0) local z = vmath.vector3(0, 0, 1) local rot1 = vmath.quat_basis(rot_x, rot_y, z) local rot2 = vmath.quat_from_to(vmath.vector3(0, 1, 0), vmath.vector3(1, 0, 0)) if rot1 == rot2 then -- These quaternions are equal! print(rot2) --> vmath.quat(0, 0, -0.70710676908493, 0.70710676908493) end ``` ### vmath.quat_from_to *Type:* FUNCTION The resulting quaternion describes the rotation that, if applied to the first vector, would rotate the first vector to the second. The two vectors must be unit vectors (of length 1). The result is undefined if the two vectors point in opposite directions **Parameters** - `v1` (vector3) - first unit vector, before rotation - `v2` (vector3) - second unit vector, after rotation **Returns** - `q` (quaternion) - quaternion representing the rotation from first to second vector **Examples** ``` local v1 = vmath.vector3(1, 0, 0) local v2 = vmath.vector3(0, 1, 0) local rot = vmath.quat_from_to(v1, v2) print(vmath.rotate(rot, v1)) --> vmath.vector3(0, 0.99999994039536, 0) ``` ### vmath.quat_matrix4 *Type:* FUNCTION Creates a new quaternion with the components set according to the supplied parameter values. **Parameters** - `matrix` (matrix4) - source matrix4 **Returns** - `q` (quaternion) - new quaternion ### vmath.quat_rotation_x *Type:* FUNCTION The resulting quaternion describes a rotation of angle radians around the x-axis. **Parameters** - `angle` (number) - angle in radians around x-axis **Returns** - `q` (quaternion) - quaternion representing the rotation around the x-axis **Examples** ``` local rot = vmath.quat_rotation_x(3.141592653) local vec = vmath.vector3(1, 1, 0) print(vmath.rotate(rot, vec)) --> vmath.vector3(1, -1, -8.7422776573476e-08) ``` ### vmath.quat_rotation_y *Type:* FUNCTION The resulting quaternion describes a rotation of angle radians around the y-axis. **Parameters** - `angle` (number) - angle in radians around y-axis **Returns** - `q` (quaternion) - quaternion representing the rotation around the y-axis **Examples** ``` local rot = vmath.quat_rotation_y(3.141592653) local vec = vmath.vector3(1, 1, 0) print(vmath.rotate(rot, vec)) --> vmath.vector3(-1, 1, 8.7422776573476e-08) ``` ### vmath.quat_rotation_z *Type:* FUNCTION The resulting quaternion describes a rotation of angle radians around the z-axis. **Parameters** - `angle` (number) - angle in radians around z-axis **Returns** - `q` (quaternion) - quaternion representing the rotation around the z-axis **Examples** ``` local rot = vmath.quat_rotation_z(3.141592653) local vec = vmath.vector3(1, 1, 0) print(vmath.rotate(rot, vec)) --> vmath.vector3(-0.99999988079071, -1, 0) ``` ### vmath.quat_to_euler *Type:* FUNCTION Converts a quaternion into euler angles (r0, r1, r2), based on YZX rotation order. To handle gimbal lock (singularity at r1 ~ +/- 90 degrees), the cut off is at r0 = +/- 88.85 degrees, which snaps to +/- 90. The provided quaternion is expected to be normalized. The error is guaranteed to be less than +/- 0.02 degrees **Parameters** - `q` (quaternion) - source quaternion **Returns** - `x` (number) - euler angle x in degrees - `y` (number) - euler angle y in degrees - `z` (number) - euler angle z in degrees **Examples** ``` local q = vmath.quat_rotation_z(math.rad(90)) print(vmath.quat_to_euler(q)) --> 0 0 90 local q2 = vmath.quat_rotation_y(math.rad(45)) * vmath.quat_rotation_z(math.rad(90)) local v = vmath.vector3(vmath.quat_to_euler(q2)) print(v) --> vmath.vector3(0, 45, 90) ``` ### vmath.rotate *Type:* FUNCTION Returns a new vector from the supplied vector that is rotated by the rotation described by the supplied quaternion. **Parameters** - `q` (quaternion) - quaternion - `v1` (vector3) - vector to rotate **Returns** - `v` (vector3) - the rotated vector **Examples** ``` local vec = vmath.vector3(1, 1, 0) local rot = vmath.quat_rotation_z(3.141592563) print(vmath.rotate(rot, vec)) --> vmath.vector3(-1.0000002384186, -0.99999988079071, 0) ``` ### vmath.slerp *Type:* FUNCTION Spherically interpolates between two vectors. The difference to lerp is that slerp treats the vectors as directions instead of positions in space. The direction of the returned vector is interpolated by the angle and the magnitude is interpolated between the magnitudes of the from and to vectors. Slerp is computationally more expensive than lerp. The function does not clamp t between 0 and 1. **Parameters** - `t` (number) - interpolation parameter, 0-1 - `v1` (vector3 | vector4) - vector to slerp from - `v2` (vector3 | vector4) - vector to slerp to **Returns** - `v` (vector3 | vector4) - the slerped vector **Examples** ``` function init(self) self.t = 0 end function update(self, dt) self.t = self.t + dt if self.t <= 1 then local startpos = vmath.vector3(0, 600, 0) local endpos = vmath.vector3(600, 0, 0) local pos = vmath.slerp(self.t, startpos, endpos) go.set_position(pos, "go") end end ``` ### vmath.slerp *Type:* FUNCTION Slerp travels the torque-minimal path maintaining constant velocity, which means it travels along the straightest path along the rounded surface of a sphere. Slerp is useful for interpolation of rotations. Slerp travels the torque-minimal path, which means it travels along the straightest path the rounded surface of a sphere. The function does not clamp t between 0 and 1. **Parameters** - `t` (number) - interpolation parameter, 0-1 - `q1` (quaternion) - quaternion to slerp from - `q2` (quaternion) - quaternion to slerp to **Returns** - `q` (quaternion) - the slerped quaternion **Examples** ``` function init(self) self.t = 0 end function update(self, dt) self.t = self.t + dt if self.t <= 1 then local startrot = vmath.quat_rotation_z(0) local endrot = vmath.quat_rotation_z(3.141592653) local rot = vmath.slerp(self.t, startrot, endrot) go.set_rotation(rot, "go") end end ``` ### vmath.vector *Type:* FUNCTION Creates a vector of arbitrary size. The vector is initialized with numeric values from a table. The table values are converted to floating point values. If a value cannot be converted, a 0 is stored in that value position in the vector. **Parameters** - `t` (table) - table of numbers **Returns** - `v` (vector) - new vector **Examples** How to create a vector with custom data to be used for animation easing: ``` local values = { 0, 0.5, 0 } local vec = vmath.vector(values) print(vec) --> vmath.vector (size: 3) print(vec[2]) --> 0.5 ``` ### vmath.vector3 *Type:* FUNCTION Creates a new zero vector with all components set to 0. **Returns** - `v` (vector3) - new zero vector **Examples** ``` local vec = vmath.vector3() pprint(vec) --> vmath.vector3(0, 0, 0) print(vec.x) --> 0 ``` ### vmath.vector3 *Type:* FUNCTION Creates a new vector with all components set to the supplied scalar value. **Parameters** - `n` (number) - scalar value to splat **Returns** - `v` (vector3) - new vector **Examples** ``` local vec = vmath.vector3(1.0) print(vec) --> vmath.vector3(1, 1, 1) print(vec.x) --> 1 ``` ### vmath.vector3 *Type:* FUNCTION Creates a new vector with all components set to the corresponding values from the supplied vector. I.e. This function creates a copy of the given vector. **Parameters** - `v1` (vector3) - existing vector **Returns** - `v` (vector3) - new vector **Examples** ``` local vec1 = vmath.vector3(1.0) local vec2 = vmath.vector3(vec1) if vec1 == vec2 then -- yes, they are equal print(vec2) --> vmath.vector3(1, 1, 1) end ``` ### vmath.vector3 *Type:* FUNCTION Creates a new vector with the components set to the supplied values. **Parameters** - `x` (number) - x coordinate - `y` (number) - y coordinate - `z` (number) - z coordinate **Returns** - `v` (vector3) - new vector **Examples** ``` local vec = vmath.vector3(1.0, 2.0, 3.0) print(vec) --> vmath.vector3(1, 2, 3) print(-vec) --> vmath.vector3(-1, -2, -3) print(vec * 2) --> vmath.vector3(2, 4, 6) print(vec + vmath.vector3(2.0)) --> vmath.vector3(3, 4, 5) print(vec - vmath.vector3(2.0)) --> vmath.vector3(-1, 0, 1) ``` ### vmath.vector4 *Type:* FUNCTION Creates a new zero vector with all components set to 0. **Returns** - `v` (vector4) - new zero vector **Examples** ``` local vec = vmath.vector4() print(vec) --> vmath.vector4(0, 0, 0, 0) print(vec.w) --> 0 ``` ### vmath.vector4 *Type:* FUNCTION Creates a new vector with all components set to the supplied scalar value. **Parameters** - `n` (number) - scalar value to splat **Returns** - `v` (vector4) - new vector **Examples** ``` local vec = vmath.vector4(1.0) print(vec) --> vmath.vector4(1, 1, 1, 1) print(vec.w) --> 1 ``` ### vmath.vector4 *Type:* FUNCTION Creates a new vector with all components set to the corresponding values from the supplied vector. I.e. This function creates a copy of the given vector. **Parameters** - `v1` (vector4) - existing vector **Returns** - `v` (vector4) - new vector **Examples** ``` local vect1 = vmath.vector4(1.0) local vect2 = vmath.vector4(vec1) if vec1 == vec2 then -- yes, they are equal print(vec2) --> vmath.vector4(1, 1, 1, 1) end ``` ### vmath.vector4 *Type:* FUNCTION Creates a new vector with the components set to the supplied values. **Parameters** - `x` (number) - x coordinate - `y` (number) - y coordinate - `z` (number) - z coordinate - `w` (number) - w coordinate **Returns** - `v` (vector4) - new vector **Examples** ``` local vec = vmath.vector4(1.0, 2.0, 3.0, 4.0) print(vec) --> vmath.vector4(1, 2, 3, 4) print(-vec) --> vmath.vector4(-1, -2, -3, -4) print(vec * 2) --> vmath.vector4(2, 4, 6, 8) print(vec + vmath.vector4(2.0)) --> vmath.vector4(3, 4, 5, 6) print(vec - vmath.vector4(2.0)) --> vmath.vector4(-1, 0, 1, 2) ``` # Window {#apis:window-lua} **Namespace:** `window` **Language:** Lua **Type:** Defold Lua **File:** `script_window.cpp` **Source:** `engine/gamesys/src/gamesys/scripts/script_window.cpp` Functions and constants to access the window, window event listeners and screen dimming. ## API ### window.DIMMING_OFF *Type:* CONSTANT Dimming mode is used to control whether or not a mobile device should dim the screen after a period without user interaction. ### window.DIMMING_ON *Type:* CONSTANT Dimming mode is used to control whether or not a mobile device should dim the screen after a period without user interaction. ### window.DIMMING_UNKNOWN *Type:* CONSTANT Dimming mode is used to control whether or not a mobile device should dim the screen after a period without user interaction. This mode indicates that the dim mode can't be determined, or that the platform doesn't support dimming. ### window.get_dim_mode *Type:* FUNCTION Returns the current dimming mode set on a mobile device. The dimming mode specifies whether or not a mobile device should dim the screen after a period without user interaction. On platforms that does not support dimming, window.DIMMING_UNKNOWN is always returned. **Returns** - `mode` (constant) - The mode for screen dimming
  • window.DIMMING_UNKNOWN
  • window.DIMMING_ON
  • window.DIMMING_OFF
### window.get_display_scale *Type:* FUNCTION This returns the content scale of the current display. **Returns** - `scale` (number) - The display scale ### window.get_mouse_lock *Type:* FUNCTION This returns the current lock state of the mouse cursor **Returns** - `state` (boolean) - The lock state ### window.get_safe_area *Type:* FUNCTION This returns the safe area rectangle (x, y, width, height) and the inset values relative to the window edges. On platforms without a safe area, this returns the full window size and zero insets. **Returns** - `safe_area` (table) - safe area data
safe_area
table table containing these keys:
  • number x
  • number y
  • number width
  • number height
  • number inset_left
  • number inset_top
  • number inset_right
  • number inset_bottom
### window.get_size *Type:* FUNCTION This returns the current window size (width and height). **Returns** - `width` (number) - The window width - `height` (number) - The window height ### window.set_dim_mode *Type:* FUNCTION Sets the dimming mode on a mobile device. The dimming mode specifies whether or not a mobile device should dim the screen after a period without user interaction. The dimming mode will only affect the mobile device while the game is in focus on the device, but not when the game is running in the background. This function has no effect on platforms that does not support dimming. **Parameters** - `mode` (constant) - The mode for screen dimming
  • window.DIMMING_ON
  • window.DIMMING_OFF
### window.set_listener *Type:* FUNCTION Sets a window event listener. Only one window event listener can be set at a time. **Parameters** - `callback` (function(self, event, data) | nil) - A callback which receives info about window events. Pass an empty function or nil if you no longer wish to receive callbacks.
self
object The calling script
event
constant The type of event. Can be one of these:
  • window.WINDOW_EVENT_FOCUS_LOST
  • window.WINDOW_EVENT_FOCUS_GAINED
  • window.WINDOW_EVENT_RESIZED
  • window.WINDOW_EVENT_ICONIFIED
  • window.WINDOW_EVENT_DEICONIFIED
data
table The callback value data is a table which currently holds these values
  • number width: The width of a resize event. nil otherwise.
  • number height: The height of a resize event. nil otherwise.
**Examples** ``` function window_callback(self, event, data) if event == window.WINDOW_EVENT_FOCUS_LOST then print("window.WINDOW_EVENT_FOCUS_LOST") elseif event == window.WINDOW_EVENT_FOCUS_GAINED then print("window.WINDOW_EVENT_FOCUS_GAINED") elseif event == window.WINDOW_EVENT_ICONFIED then print("window.WINDOW_EVENT_ICONFIED") elseif event == window.WINDOW_EVENT_DEICONIFIED then print("window.WINDOW_EVENT_DEICONIFIED") elseif event == window.WINDOW_EVENT_RESIZED then print("Window resized: ", data.width, data.height) end end function init(self) window.set_listener(window_callback) end ``` ### window.set_mouse_lock *Type:* FUNCTION Set the locking state for current mouse cursor on a PC platform. This function locks or unlocks the mouse cursor to the center point of the window. While the cursor is locked, mouse position updates will still be sent to the scripts as usual. **Parameters** - `flag` (boolean) - The lock state for the mouse cursor ### window.set_position *Type:* FUNCTION Sets the window position. **Parameters** - `x` (number) - Horizontal position of window - `y` (number) - Vertical position of window ### window.set_size *Type:* FUNCTION Sets the window size. Works on desktop platforms only. **Parameters** - `width` (number) - Width of window - `height` (number) - Height of window ### window.set_title *Type:* FUNCTION Sets the window title. Works on desktop platforms. **Parameters** - `title` (string) - The title, encoded as UTF-8 ### window.WINDOW_EVENT_DEICONIFIED *Type:* CONSTANT This event is sent to a window event listener when the game window or app screen is restored after being iconified. ### window.WINDOW_EVENT_FOCUS_GAINED *Type:* CONSTANT This event is sent to a window event listener when the game window or app screen has gained focus. This event is also sent at game startup and the engine gives focus to the game. ### window.WINDOW_EVENT_FOCUS_LOST *Type:* CONSTANT This event is sent to a window event listener when the game window or app screen has lost focus. ### window.WINDOW_EVENT_ICONFIED *Type:* CONSTANT This event is sent to a window event listener when the game window or app screen is iconified (reduced to an application icon in a toolbar, application tray or similar). ### window.WINDOW_EVENT_RESIZED *Type:* CONSTANT This event is sent to a window event listener when the game window or app screen is resized. The new size is passed along in the data field to the event listener. # Zlib {#apis:zlib-lua} **Namespace:** `zlib` **Language:** Lua **Type:** Defold Lua **File:** `script_zlib.cpp` **Source:** `engine/script/src/script_zlib.cpp` Functions for compression and decompression of string buffers. ## API ### zlib.deflate *Type:* FUNCTION A lua error is raised is on error **Parameters** - `buf` (string) - buffer to deflate **Returns** - `buf` (string) - deflated buffer **Examples** ``` local data = "This is a string with uncompressed data." local compressed_data = zlib.deflate(data) local s = "" for c in string.gmatch(compressed_data, ".") do s = s .. '\\' .. string.byte(c) end print(s) --> \120\94\11\201\200\44\86\0\162\68\133\226\146\162 ... ``` ### zlib.inflate *Type:* FUNCTION A lua error is raised is on error **Parameters** - `buf` (string) - buffer to inflate **Returns** - `buf` (string) - inflated buffer **Examples** ``` local data = "\120\94\11\201\200\44\86\0\162\68\133\226\146\162\204\188\116\133\242\204\146\12\133\210\188\228\252\220\130\162\212\226\226\212\20\133\148\196\146\68\61\0\44\67\14\201" local uncompressed_data = zlib.inflate(data) print(uncompressed_data) --> This is a string with uncompressed data. ``` # extension-adinfo {#apis:extension-adinfo_adinfo} **Namespace:** `adinfo` **Language:** Lua **Type:** Extension Provides functionality to get the advertising id and tracking status. Supported on iOS and Android. [icon:ios] [icon:android] ## API ### adinfo.get *Type:* FUNCTION Get a table with advertising information. [icon:attention] function returns nil if values do not ready **Examples** ``` function init(self) adinfo.get(function(self, info) print(info.ad_ident, info.ad_tracking_enabled) end) end ``` # extension-admob {#apis:extension-admob_admob} **Namespace:** `admob` **Language:** Lua **Type:** Extension Functions and constants for interacting with [Google AdMob APIs](https://developers.google.com/admob) ## API ### admob.initialize *Type:* FUNCTION Initialize the Mobile Ads SDK. Warning: If you need to obtain consent from users in the European Economic Area (EEA), set any request-specific flags, or otherwise take action before loading ads, ensure you do so before initializing the Mobile Ads SDK. Original docs [Android](https://developers.google.com/admob/android/quick-start#initialize_the_mobile_ads_sdk), [iOS](https://developers.google.com/admob/ios/quick-start#initialize_the_mobile_ads_sdk) ### admob.set_callback *Type:* FUNCTION Sets a callback function for receiving events from the SDK. Call `admob.set_callback(nil)` to remove callback **Parameters** - `callback` (function) - Callback function that is executed on any event in the SDK. - `self` (object) - The calling script instance - `message_id` (number) - One of message types: `admob.MSG_INITIALIZATION` initialization, `admob.MSG_INTERSTITIAL` message from Interstitial ad unit, `admob.MSG_REWARDED` message from Rewarded ad unit, `admob.MSG_BANNER` message from Banner ad unit - `message` (table) - A table holding the data - `event` (number) - One of event types: `admob.EVENT_CLOSED`, `admob.EVENT_FAILED_TO_SHOW`, `admob.EVENT_OPENING`, `admob.EVENT_FAILED_TO_LOAD`, `admob.EVENT_LOADED`, `admob.EVENT_NOT_LOADED`, `admob.EVENT_EARNED_REWARD`, `admob.EVENT_COMPLETE`, `admob.EVENT_CLICKED`, `admob.EVENT_DESTROYED`, `admob.EVENT_IMPRESSION_RECORDED`, `admob.EVENT_JSON_ERROR` - `code` (number) - The error code (if an error occurred or `nil` otherwise) - `message` (string) - The error message (if an error occurred or `nil` otherwise) **Examples** ``` local function admob_callback(self, message_id, message) pprint(message_id, message) if message_id == admob.MSG_INITIALIZATION then if message.event == admob.EVENT_COMPLETE then print("EVENT_COMPLETE: Initialization complete") elseif message.event == admob.EVENT_JSON_ERROR then print("EVENT_JSON_ERROR: Internal NE json error "..message.error) end elseif message_id == admob.MSG_IDFA then if message.event == admob.EVENT_STATUS_AUTHORIZED then print("EVENT_STATUS_AUTHORIZED: ATTrackingManagerAuthorizationStatusAuthorized") elseif message.event == admob.EVENT_STATUS_DENIED then print("EVENT_STATUS_DENIED: ATTrackingManagerAuthorizationStatusDenied") elseif message.event == admob.EVENT_STATUS_NOT_DETERMINED then print("EVENT_STATUS_NOT_DETERMINED: ATTrackingManagerAuthorizationStatusNotDetermined") elseif message.event == admob.EVENT_STATUS_RESTRICTED then print("EVENT_STATUS_RESTRICTED: ATTrackingManagerAuthorizationStatusRestricted") elseif message.event == admob.EVENT_NOT_SUPPORTED then print("EVENT_NOT_SUPPORTED: IDFA request not supported on this platform or OS version") end elseif message_id == admob.MSG_INTERSTITIAL then if message.event == admob.EVENT_CLOSED then print("EVENT_CLOSED: Interstitial AD closed") elseif message.event == admob.EVENT_FAILED_TO_SHOW then print("EVENT_FAILED_TO_SHOW: Interstitial AD failed to show\nCode: "..message.code.."\nError: "..message.error) elseif message.event == admob.EVENT_OPENING then print("EVENT_OPENING: Interstitial AD is opening") elseif message.event == admob.EVENT_FAILED_TO_LOAD then print("EVENT_FAILED_TO_LOAD: Interstitial AD failed to load\nCode: "..message.code.."\nError: "..message.error) elseif message.event == admob.EVENT_LOADED then print("EVENT_LOADED: Interstitial AD loaded") elseif message.event == admob.EVENT_NOT_LOADED then print("EVENT_NOT_LOADED: can't call show_interstitial() before EVENT_LOADED\nError: "..message.error) elseif message.event == admob.EVENT_IMPRESSION_RECORDED then print("EVENT_IMPRESSION_RECORDED: Interstitial did record impression") elseif message.event == admob.EVENT_JSON_ERROR then print("EVENT_JSON_ERROR: Internal NE json error: "..message.error) end elseif message_id == admob.MSG_REWARDED then if message.event == admob.EVENT_CLOSED then print("EVENT_CLOSED: Rewarded AD closed") elseif message.event == admob.EVENT_FAILED_TO_SHOW then print("EVENT_FAILED_TO_SHOW: Rewarded AD failed to show\nCode: "..message.code.."\nError: "..message.error) elseif message.event == admob.EVENT_OPENING then print("EVENT_OPENING: Rewarded AD is opening") elseif message.event == admob.EVENT_FAILED_TO_LOAD then print("EVENT_FAILED_TO_LOAD: Rewarded AD failed to load\nCode: "..message.code.."\nError: "..message.error) elseif message.event == admob.EVENT_LOADED then print("EVENT_LOADED: Rewarded AD loaded") elseif message.event == admob.EVENT_NOT_LOADED then print("EVENT_NOT_LOADED: can't call show_rewarded() before EVENT_LOADED\nError: "..message.error) elseif message.event == admob.EVENT_EARNED_REWARD then print("EVENT_EARNED_REWARD: Reward: " .. tostring(message.amount) .. " " .. tostring(message.type)) elseif message.event == admob.EVENT_IMPRESSION_RECORDED then print("EVENT_IMPRESSION_RECORDED: Rewarded did record impression") elseif message.event == admob.EVENT_JSON_ERROR then print("EVENT_JSON_ERROR: Internal NE json error: "..message.error) end elseif message_id == admob.MSG_BANNER then if message.event == admob.EVENT_LOADED then print("EVENT_LOADED: Banner AD loaded. Height: "..message.height.."px Width: "..message.width.."px") elseif message.event == admob.EVENT_OPENING then print("EVENT_OPENING: Banner AD is opening") elseif message.event == admob.EVENT_FAILED_TO_LOAD then print("EVENT_FAILED_TO_LOAD: Banner AD failed to load\nCode: "..message.code.."\nError: "..message.error) elseif message.event == admob.EVENT_CLICKED then print("EVENT_CLICKED: Banner AD loaded") elseif message.event == admob.EVENT_CLOSED then print("EVENT_CLOSED: Banner AD closed") elseif message.event == admob.EVENT_DESTROYED then print("EVENT_DESTROYED: Banner AD destroyed") elseif message.event == admob.EVENT_IMPRESSION_RECORDED then print("EVENT_IMPRESSION_RECORDED: Banner did record impression") elseif message.event == admob.EVENT_JSON_ERROR then print("EVENT_JSON_ERROR: Internal NE json error: "..message.error) end end end function init(self) if admob then admob.set_callback(admob_callback) admob.initialize() end end ``` ### admob.set_privacy_settings *Type:* FUNCTION Sets user privacy preferences (must be called before `admob.initialize()`). Original docs [Android](https://developers.google.com/admob/android/ccpa), [iOS](https://developers.google.com/admob/ios/ccpa) **Parameters** - `bool` (boolean) ### admob.request_idfa *Type:* FUNCTION Display the App Tracking Transparency authorization request for accessing the IDFA. Original docs [iOS](https://developers.google.com/admob/ios/ios14#request) ### admob.show_ad_inspector *Type:* FUNCTION Show Ad Inspector. This is an in-app overlay that enables authorized devices to perform realtime analysis of test ad requests directly within a mobile app. Ad Inspector only launces on [test devices](https://support.google.com/admob/answer/9691433). Original docs [Android](https://developers.google.com/admob/android/ad-inspector), [iOS](https://developers.google.com/admob/ios/ad-inspector) ### admob.load_appopen *Type:* FUNCTION Starts loading an AppOpen Ad, can only be called after `admob.MSG_INITIALIZATION` event Original docs [Android](https://developers.google.com/admob/android/app-open), [iOS](https://developers.google.com/admob/ios/app-open) **Parameters** - `ad_unit_id` (string) - Ad unit ID, for test ads use on Android `"ca-app-pub-3940256099942544/9257395921"`, or on iOS `"ca-app-pub-3940256099942544/5575463023"` Original docs [Android](https://developers.google.com/admob/android/app-open), [iOS](https://developers.google.com/admob/ios/app-open) ### admob.show_appopen *Type:* FUNCTION Shows loaded AppOpen Ad, can only be called after `admob.EVENT_LOADED` Original docs [Android](https://developers.google.com/admob/android/app-open), [iOS](https://developers.google.com/admob/ios/app-open) **Examples** ``` if admob and admob.is_appopen_loaded() then admob.show_appopen() end ``` ### admob.is_appopen_loaded *Type:* FUNCTION Checks if AppOpen Ad is loaded and ready to show Original docs [Android](https://developers.google.com/admob/android/app-open), [iOS](https://developers.google.com/admob/ios/app-open) **Returns** - `boolean` ### admob.load_interstitial *Type:* FUNCTION Starts loading an Interstitial Ad, can only be called after `admob.MSG_INITIALIZATION` event Original docs [Android](https://developers.google.com/admob/android/interstitial-fullscreen), [iOS](https://developers.google.com/admob/ios/interstitial) **Parameters** - `ad_unit_id` (string) - Ad unit ID, for test ads use on Android `"ca-app-pub-3940256099942544/1033173712"`, or on iOS `"ca-app-pub-3940256099942544/4411468910"` Original docs [Android](https://developers.google.com/admob/android/interstitial-fullscreen), [iOS](https://developers.google.com/admob/ios/interstitial) ### admob.show_interstitial *Type:* FUNCTION Shows loaded Interstitial Ad, can only be called after `admob.EVENT_LOADED` Original docs [Android](https://developers.google.com/admob/android/interstitial-fullscreen), [iOS](https://developers.google.com/admob/ios/interstitial) **Examples** ``` if admob and admob.is_interstitial_loaded() then admob.show_interstitial() end ``` ### admob.is_interstitial_loaded *Type:* FUNCTION Checks if Interstitial Ad is loaded and ready to show Original docs [Android](https://developers.google.com/admob/android/interstitial-fullscreen), [iOS](https://developers.google.com/admob/ios/interstitial) **Returns** - `boolean` ### admob.load_rewarded *Type:* FUNCTION Starts loading a Rewarded Ad, can only be called after `admob.MSG_INITIALIZATION` event Original docs [Android](https://developers.google.com/admob/android/rewarded-fullscreen), [iOS](https://developers.google.com/admob/ios/rewarded-ads) **Parameters** - `ad_unit_id` (string) - Ad unit ID, for test ads use on Android `"ca-app-pub-3940256099942544/1712485313"`, or on iOS `"ca-app-pub-3940256099942544/4411468910"` Original docs [Android](https://developers.google.com/admob/android/rewarded-fullscreen), [iOS](https://developers.google.com/admob/ios/rewarded-ads) - `options` (table) - ServerSideVerificationOptions [Android](https://developers.google.com/admob/android/rewarded#validate-ssv), [iOS](https://developers.google.com/admob/ios/rewarded#validate-ssv) - `user_id` (string) - A unique identifier assigned to each user. - `custom_data` (string) - Custom Data attached to server-side reward callbacks. ### admob.show_rewarded *Type:* FUNCTION Shows loaded Rewarded Ad, can only be called after `admob.EVENT_LOADED` Original docs [Android](https://developers.google.com/admob/android/rewarded-fullscreen), [iOS](https://developers.google.com/admob/ios/rewarded-ads) **Examples** ``` if admob and admob.is_rewarded_loaded() then admob.show_rewarded() end ``` ### admob.is_rewarded_loaded *Type:* FUNCTION Checks if Rewarded Ad is loaded and ready to show Original docs [Android](https://developers.google.com/admob/android/rewarded-fullscreen), [iOS](https://developers.google.com/admob/ios/rewarded-ads) **Returns** - `boolean` ### admob.load_rewarded_interstitial *Type:* FUNCTION Starts loading a Rewarded Interstitial Ad, can only be called after `admob.MSG_INITIALIZATION` event Original docs [Android](https://developers.google.com/admob/android/rewarded-interstitial#load_an_ad), [iOS](https://developers.google.com/admob/ios/rewarded-interstitial#load_an_ad) **Parameters** - `ad_unit_id` (string) - Ad unit ID, for test ads use on Android `"ca-app-pub-3940256099942544/5354046379"`, or on iOS `"ca-app-pub-3940256099942544/6978759866"` Original docs [Android](https://developers.google.com/admob/android/rewarded-interstitial#load_an_ad), [iOS](https://developers.google.com/admob/ios/rewarded-interstitial#load_an_ad) ### admob.show_rewarded_interstitial *Type:* FUNCTION Shows loaded Rewarded Interstitial Ad, can only be called after `admob.EVENT_LOADED` Original docs [Android](https://developers.google.com/admob/android/rewarded-interstitial#show_the_ad), [iOS](https://developers.google.com/admob/ios/rewarded-interstitial#display_the_ad_and_handle_the_reward_event) **Examples** ``` if admob and admob.is_rewarded_interstitial_loaded() then admob.show_rewarded_interstitial() end ``` ### admob.is_rewarded_interstitial_loaded *Type:* FUNCTION Checks if Rewarded Interstitial Ad is loaded and ready to show Original docs [Android](https://developers.google.com/admob/android/rewarded-interstitial), [iOS](https://developers.google.com/admob/ios/rewarded-interstitial) **Returns** - `boolean` ### admob.load_banner *Type:* FUNCTION Starts loading a Banner Ad, can only be called after `admob.MSG_INITIALIZATION` event Original docs [Android](https://developers.google.com/admob/android/banner), [iOS](https://developers.google.com/admob/ios/banner) **Parameters** - `ad_unit_id` (string) - Ad unit ID, for test ads use on Android `"ca-app-pub-3940256099942544/6300978111"`, or on iOS `"ca-app-pub-3940256099942544/2934735716"` Original docs [Android](https://developers.google.com/admob/android/banner), [iOS](https://developers.google.com/admob/ios/banner) - `size` (number) - Requested Banner Ad size, possible values: `admob.SIZE_ADAPTIVE_BANNER` (default), `admob.SIZE_BANNER`, `admob.SIZE_FLUID`, `admob.SIZE_FULL_BANNER`, `admob.SIZE_LARGE_BANNER`, `admob.SIZE_LEADEARBOARD`, `admob.SIZE_MEDIUM_RECTANGLE`, `admob.SIZE_SMART_BANNER`, `admob.SIZE_LARGE_ADAPTIVE_BANNER` Original docs [Android](https://developers.google.com/admob/android/banner#banner_sizes), [iOS](https://developers.google.com/admob/ios/banner#banner_sizes) ### admob.show_banner *Type:* FUNCTION Shows loaded Banner Ad, can only be called after `admob.EVENT_LOADED` Original docs [Android](https://developers.google.com/admob/android/banner), [iOS](https://developers.google.com/admob/ios/banner) **Parameters** - `position` (number) - Banner Ad position, possible values: `admob.POS_NONE` (default), `admob.POS_TOP_LEFT`, `admob.POS_TOP_CENTER`, `admob.POS_TOP_RIGHT`, `admob.POS_BOTTOM_LEFT`, `admob.POS_BOTTOM_CENTER`, `admob.POS_BOTTOM_RIGHT`, `admob.POS_CENTER` **Examples** ``` if admob and admob.is_banner_loaded() then admob.show_banner(admob.POS_TOP_CENTER) end ``` ### admob.set_max_ad_content_rating *Type:* FUNCTION Sets a maximum ad content rating. AdMob ads returned for your app will have a content rating at or below that level. Original docs [Android](https://developers.google.com/admob/android/targeting#ad_content_filtering), [iOS](https://developers.google.com/admob/ios/targeting#ad_content_filtering) **Parameters** - `max_ad_rating` (number) - Max Ad Rating, possible values: `admob.MAX_AD_CONTENT_RATING_G`, `admob.MAX_AD_CONTENT_RATING_PG`, `admob.MAX_AD_CONTENT_RATING_T`, `admob.MAX_AD_CONTENT_RATING_MA` **Examples** ``` admob.set_max_ad_content_rating(admob.MAX_AD_CONTENT_RATING_PG) ``` ### admob.hide_banner *Type:* FUNCTION Temporarily hides Banner Ad, banner can be shown again using `admob.show_banner()` Original docs [Android](https://developers.google.com/admob/android/banner), [iOS](https://developers.google.com/admob/ios/banner) ### admob.is_banner_loaded *Type:* FUNCTION Checks if Banner Ad is loaded and ready to show Original docs [Android](https://developers.google.com/admob/android/banner), [iOS](https://developers.google.com/admob/ios/banner) **Returns** - `boolean` ### admob.destroy_banner *Type:* FUNCTION Hides and unloads Banner Ad (needs to call `admob.load_banner()` later to show Banner Ad) Original docs [Android](https://developers.google.com/admob/android/banner), [iOS](https://developers.google.com/admob/ios/banner) ### MSG_INITIALIZATION *Type:* VARIABLE ### MSG_INTERSTITIAL *Type:* VARIABLE ### MSG_REWARDED *Type:* VARIABLE ### MSG_BANNER *Type:* VARIABLE ### MSG_IDFA *Type:* VARIABLE ### MSG_REWARDED_INTERSTITIAL *Type:* VARIABLE ### MSG_APPOPEN *Type:* VARIABLE ### EVENT_CLOSED *Type:* VARIABLE ### EVENT_FAILED_TO_SHOW *Type:* VARIABLE ### EVENT_OPENING *Type:* VARIABLE ### EVENT_FAILED_TO_LOAD *Type:* VARIABLE ### EVENT_LOADED *Type:* VARIABLE ### EVENT_NOT_LOADED *Type:* VARIABLE ### EVENT_EARNED_REWARD *Type:* VARIABLE ### EVENT_COMPLETE *Type:* VARIABLE ### EVENT_CLICKED *Type:* VARIABLE ### EVENT_DESTROYED *Type:* VARIABLE ### EVENT_JSON_ERROR *Type:* VARIABLE ### EVENT_IMPRESSION_RECORDED *Type:* VARIABLE ### EVENT_STATUS_AUTHORIZED *Type:* VARIABLE ### EVENT_STATUS_DENIED *Type:* VARIABLE ### EVENT_STATUS_NOT_DETERMINED *Type:* VARIABLE ### EVENT_STATUS_RESTRICTED *Type:* VARIABLE ### EVENT_NOT_SUPPORTED *Type:* VARIABLE ### SIZE_ADAPTIVE_BANNER *Type:* VARIABLE ### SIZE_LARGE_ADAPTIVE_BANNER *Type:* VARIABLE ### SIZE_BANNER *Type:* VARIABLE ### SIZE_FLUID *Type:* VARIABLE ### SIZE_FULL_BANNER *Type:* VARIABLE ### SIZE_LARGE_BANNER *Type:* VARIABLE ### SIZE_LEADEARBOARD *Type:* VARIABLE ### SIZE_MEDIUM_RECTANGLE *Type:* VARIABLE ### SIZE_SMART_BANNER *Type:* VARIABLE ### POS_NONE *Type:* VARIABLE ### POS_TOP_LEFT *Type:* VARIABLE ### POS_TOP_CENTER *Type:* VARIABLE ### POS_TOP_RIGHT *Type:* VARIABLE ### POS_BOTTOM_LEFT *Type:* VARIABLE ### POS_BOTTOM_CENTER *Type:* VARIABLE ### POS_BOTTOM_RIGHT *Type:* VARIABLE ### POS_CENTER *Type:* VARIABLE ### MAX_AD_CONTENT_RATING_G *Type:* VARIABLE ### MAX_AD_CONTENT_RATING_PG *Type:* VARIABLE ### MAX_AD_CONTENT_RATING_T *Type:* VARIABLE ### MAX_AD_CONTENT_RATING_MA *Type:* VARIABLE # extension-adpf {#apis:extension-adpf_adpf} **Namespace:** `adpf` **Language:** Lua **Type:** Extension Functions and constants for interacting with the Android Device Performance Framework ## API ### adpf.hint.initialize *Type:* FUNCTION Initialise performance hints **Parameters** - `target_fps_nanos` (number) **Returns** - `boolean` - Return true if the PerformanceHintManager API is available on the device ### adpf.hint.update_target_fps *Type:* FUNCTION Update the target fps **Parameters** - `target_fps_nanos` (number) ### *Type:* TABLE Functions and constants for interacting with the PerformanceHintManager ### adpf.thermal.initialize *Type:* FUNCTION Initialise thermal **Parameters** - `available` (boolean) - Return true if the Thermal API is available on the device ### adpf.thermal.get_headroom *Type:* FUNCTION Provides an estimate of how much thermal headroom the device currently has before hitting severe throttling. **Parameters** - `forecast_seconds` (number) - how many seconds in the future to forecast **Returns** - `number` - a value greater than or equal to 0.0 where 1.0 indicates the SEVERE throttling threshold ### adpf.thermal.get_status *Type:* FUNCTION Get the current thermal status of the device **Returns** - `number` - The current thermal status of the device. One of THERMAL_STATUS_XYZ. ### THERMAL_STATUS_CRITICAL *Type:* VARIABLE Platform has done everything to reduce power. ### THERMAL_STATUS_EMERGENCY *Type:* VARIABLE Key components in platform are shutting down due to thermal condition. ### THERMAL_STATUS_LIGHT *Type:* VARIABLE Light throttling where UX is not impacted. ### THERMAL_STATUS_MODERATE *Type:* VARIABLE Moderate throttling where UX is not largely impacted. ### THERMAL_STATUS_NONE *Type:* VARIABLE Not under throttling. ### THERMAL_STATUS_SEVERE *Type:* VARIABLE Severe throttling where UX is largely impacted. ### THERMAL_STATUS_SHUTDOWN *Type:* VARIABLE Need shutdown immediately ### *Type:* TABLE Functions and constants for interacting with the PowerManager ThermalAPI # extension-camera {#apis:extension-camera_camera} **Namespace:** `camera` **Language:** Lua **Type:** Extension Provides functionality to capture images using the camera. Supported on macOS, iOS and Android. [icon:ios] [icon:android] ## API ### camera.start_capture *Type:* FUNCTION Start camera capture using the specified camera (front/back) and capture quality. This may trigger a camera usage permission popup. When the popup has been dismissed the callback will be invoked with camera start status. **Examples** ``` camera.start_capture(camera.CAMERA_TYPE_BACK, camera.CAPTURE_QUALITY_HIGH, function(self, message) if message == camera.CAMERA_STARTED then -- do stuff end end) ``` ### camera.stop_capture *Type:* FUNCTION Stops a previously started capture session. **Examples** ``` camera.stop_capture() ``` ### camera.get_info *Type:* FUNCTION Gets the info from the current capture session. **Examples** ``` local info = camera.get_info() print("width", info.width) print("height", info.height) ``` ### camera.get_frame *Type:* FUNCTION Get captured frame. **Examples** ``` self.cameraframe = camera.get_frame() ``` ### CAMERA_TYPE_FRONT *Type:* STRING Constant for the front camera. ### CAMERA_TYPE_BACK *Type:* STRING Constant for the back camera. ### CAPTURE_QUALITY_HIGH *Type:* STRING High quality capture session. ### CAPTURE_QUALITY_MEDIUM *Type:* STRING Medium quality capture session. ### CAPTURE_QUALITY_LOW *Type:* STRING Low quality capture session. ### CAMERA_STARTED *Type:* STRING The capture session has started. ### CAMERA_STOPPED *Type:* STRING The capture session has stopped. ### CAMERA_NOT_PERMITTED *Type:* STRING The user did not give permission to start the capture session. ### CAMERA_ERROR *Type:* STRING Something went wrong when starting the capture session. # extension-crazygames {#apis:extension-crazygames_crazygames} **Namespace:** `crazygames` **Language:** Lua **Type:** Extension Functions and constants for interacting with the CrazyGames SDK APIs ## API ### crazygames.gameplay_start *Type:* FUNCTION The gameplayStart() function has to be called whenever the player starts playing or resumes playing after a break (menu/loading/achievement screen, game paused, etc.) ### crazygames.gameplay_stop *Type:* FUNCTION The gameplayStop() function has to be called on every game break (entering a menu, switching level, pausing the game, ...) don't forget to call gameplayStart() when the gameplay resumes ### crazygames.loading_start *Type:* FUNCTION The loadingStart() function has to be called whenever you start loading your game. ### crazygames.loading_stop *Type:* FUNCTION The loadingStop() function has to be called when the loading is complete and eventually the gameplay starts. ### crazygames.show_rewarded_ad *Type:* FUNCTION Show a rewarded ad. **Parameters** - `callback` (function) ### crazygames.show_midgame_ad *Type:* FUNCTION Show a midgame ad. **Parameters** - `callback` (function) ### crazygames.is_ad_blocked *Type:* FUNCTION Detect if the user has an adblocker. **Parameters** - `callback` (function) ### crazygames.request_banner *Type:* FUNCTION Request a banner. The container will be resized to the specified width. **Parameters** - `div` (string) - `width` (number) - `height` (number) ### crazygames.request_responsive_banner *Type:* FUNCTION The responsive banners feature will request ads that fit into your container, without the need to specify or select a size beforehand. **Parameters** - `div` (string) ### crazygames.clear_banner *Type:* FUNCTION Clear a banner. Will also hide it. **Parameters** - `div` (string) ### crazygames.clear_all_banners *Type:* FUNCTION Clear all banners. ### crazygames.invite_link *Type:* FUNCTION Create a link to your game to invite others to join a multiplayer game. **Parameters** - `params` (table) **Returns** - `string` ### crazygames.show_invite_button *Type:* FUNCTION Display a button in the game footer, that opens a popup containing an invite link. **Parameters** - `params` (table) **Returns** - `string` ### crazygames.hide_invite_button *Type:* FUNCTION Hide the invite button when it is no longer necessary. ### crazygames.get_invite_param *Type:* FUNCTION Get an invite link parameters. **Parameters** - `key` (string) **Returns** - `string` ### crazygames.is_instant_multiplayer *Type:* FUNCTION For multiplayer games, if is_instant_multiplayer() returns true, you should instantly create a new room/lobby for the user. **Returns** - `boolean` ### crazygames.clear_data *Type:* FUNCTION Remove all data items from the local storage. ### crazygames.get_item *Type:* FUNCTION Get a data item from the local storage. **Parameters** - `key` (string) **Returns** - `string` ### crazygames.remove_item *Type:* FUNCTION Remove a data item from the local storage. **Parameters** - `key` (string) ### crazygames.set_item *Type:* FUNCTION Add a data item to the local storage. **Parameters** - `key` (string) - `value` (string) ### crazygames.is_user_account_available *Type:* FUNCTION Before using any user account features, you should always ensure that the user account system is available. **Returns** - `boolean` ### crazygames.get_user *Type:* FUNCTION Retrieve the user currently logged in CrazyGames. If the user is not logged in CrazyGames, the returned user will be null. Will call the provided callback with the logged in user account. **Parameters** - `callback` (function) - The function takes two arguments, self and the user table ### crazygames.get_user_token *Type:* FUNCTION The user token is in JWT format and contains the userId of the player that is currently logged in to CrazyGames, as well as other useful information. You should send it to your server when required, and verify/decode it there to extract the userId. Will call the provided callback with the token. **Parameters** - `callback` (function) - The function takes two arguments, self and the token ### crazygames.get_xsolla_user_token *Type:* FUNCTION Generates a custom Xsolla token that you use with the Xsolla SDK. Will call the provided callback with the token. **Parameters** - `callback` (function) - The function takes two arguments, self and the xsolla token ### crazygames.show_auth_prompt *Type:* FUNCTION By calling this method, the log in or register popup will be displayed on CrazyGames. The user can log in their existing account, or create a new account. Will call the provided callback on log in. **Parameters** - `callback` (function) - The function takes two arguments, self and the user table ### crazygames.set_auth_listener *Type:* FUNCTION You can register a user auth listener that is triggered when the player logs in to CrazyGames. A log out doesn't trigger the auth listener, since the entire page is refreshed when the player logs out. **Parameters** - `callback` (function) - The function takes two arguments, self and the user table ### crazygames.remove_auth_listener *Type:* FUNCTION Remove any previously set auth listener. ### crazygames.show_account_link_prompt *Type:* FUNCTION Show an account linking prompt to link a CrazyGames account to the in-game account. # extension-crypt {#apis:extension-crypt_crypt} **Namespace:** `crypt` **Language:** Lua **Type:** Extension Functions and constants for interacting with various hash and encode/decode algorithms ## API ### crypt.hash_sha1 *Type:* FUNCTION **Parameters** - `buffer` (string) **Returns** - `string` ### crypt.hash_sha256 *Type:* FUNCTION **Parameters** - `buffer` (string) **Returns** - `string` ### crypt.hash_sha512 *Type:* FUNCTION **Parameters** - `buffer` (string) **Returns** - `string` ### crypt.hash_md5 *Type:* FUNCTION **Parameters** - `buffer` (string) **Returns** - `string` ### crypt.encode_base64 *Type:* FUNCTION **Parameters** - `input` (string) **Returns** - `string` ### crypt.decode_base64 *Type:* FUNCTION **Parameters** - `input` (string) **Returns** - `string` ### crypt.encrypt_xtea *Type:* FUNCTION **Parameters** - `source` (string) - `key` (string) - key should be <=16 **Returns** - `string` ### crypt.decrypt_xtea *Type:* FUNCTION **Parameters** - `source` (string) - `key` (string) - key should be <=16 **Returns** - `string` # extension-facebook {#apis:extension-facebook_facebook} **Namespace:** `facebook` **Language:** Lua **Type:** Extension Functions and constants for interacting with Facebook APIs ## API ### facebook.login_with_permissions *Type:* FUNCTION Login to Facebook and request a set of publish permissions. The user is prompted to authorize the application using the login dialog of the specific platform. Even if the user is already logged in to Facebook this function can still be used to request additional publish permissions. A comprehensive list of permissions can be found in the [Facebook permissions](https://developers.facebook.com/docs/facebook-login/permissions) documentation, as well as in their [guide to best practices for login management](https://developers.facebook.com/docs/facebook-login/best-practices). **Parameters** - `permissions` (table) - table with the requested publish permission strings. - `audience` (number) - The audience that should be able to see the publications. Can be any of - `facebook.AUDIENCE_NONE` - `facebook.AUDIENCE_ONLYME` - `facebook.AUDIENCE_FRIENDS` - `facebook.AUDIENCE_EVERYONE` - `callback` (function) - Callback function that is executed when the permission request dialog is closed. - `self` (object) - The context of the calling script - `data` (table) - A table that contains the response **Examples** Log in to Facebook with a set of publish permissions ``` local permissions = {"publish_actions"} facebook.login_with_permissions(permissions, facebook.AUDIENCE_FRIENDS, function(self, data) if (data.status == facebook.STATE_OPEN and data.error == nil) then print("Successfully logged into Facebook") pprint(facebook.permissions()) else print("Failed to get permissions (" .. data.status .. ")") pprint(data) end end) ``` Log in to Facebook with a set of read permissions ``` local permissions = {"public_profile", "email", "user_friends"} facebook.login_with_read_permissions(permissions, facebook.AUDIENCE_EVERYONE, function(self, data) if (data.status == facebook.STATE_OPEN and data.error == nil) then print("Successfully logged into Facebook") pprint(facebook.permissions()) else print("Failed to get permissions (" .. data.status .. ")") pprint(data) end end) ``` ### facebook.login_with_tracking_preference *Type:* FUNCTION iOS ONLY. Login to Facebook and request a set of permissions. Allows developers to signal that a login is limited in terms of tracking users. The user is prompted to authorize the application using the login dialog of the specific platform. Even if the user is already logged in to Facebook this function can still be used to request additional publish permissions. A comprehensive list of permissions can be found in the [Facebook permissions](https://developers.facebook.com/docs/facebook-login/permissions) documentation, as well as in their [guide to best practices for login management](https://developers.facebook.com/docs/facebook-login/best-practices). For Limited Login the list of permissions can be found in the [Permissions in Limited Login](https://developers.facebook.com/docs/facebook-login/limited-login/permissions) documentation. **Parameters** - `login_tracking` (number) - The tracking type for the login. Can be any of - `facebook.LOGIN_TRACKING_LIMITED` - `facebook.LOGIN_TRACKING_ENABLED` - `permissions` (table) - table with the requested publish permission strings. - `crypto_nonce` (string) - Nonce that the configuration was created with. A unique nonce will be used if none is provided to the factory method. - `callback` (function) - Callback function that is executed when the permission request dialog is closed. - `self` (object) - The context of the calling script - `data` (table) - A table that contains the response **Examples** Log in to Facebook with a set of publish permissions ``` local permissions = {"publish_actions"} facebook.login_with_permissions(permissions, facebook.AUDIENCE_FRIENDS, function(self, data) if (data.status == facebook.STATE_OPEN and data.error == nil) then print("Successfully logged into Facebook") pprint(facebook.permissions()) else print("Failed to get permissions (" .. data.status .. ")") pprint(data) end end) ``` Log in to Facebook with a set of read permissions ``` local permissions = {"public_profile", "email", "user_friends"} facebook.login_with_tracking_preference(facebook.LOGIN_TRACKING_LIMITED, permissions, "customcryptononce", function(self, data) if (data.status == facebook.STATE_OPEN and data.error == nil) then print("Successfully logged into Facebook") pprint(facebook.permissions()) else print("Failed to get permissions (" .. data.status .. ")") pprint(data) end end) ``` ### facebook.logout *Type:* FUNCTION Logout from Facebook ### facebook.set_default_audience *Type:* FUNCTION iOS ONLY. The audience that should be able to see the publications. Should be called before `facebook.login_with_tracking_preference()`; Can be any of - `facebook.AUDIENCE_NONE` - `facebook.AUDIENCE_ONLYME` - `facebook.AUDIENCE_FRIENDS` - `facebook.AUDIENCE_EVERYONE` ### facebook.get_current_authentication_token *Type:* FUNCTION iOS ONLY. Get the current AuthenticationToken. This function returns the currently stored authentication token after a previous successful login. If it returns nil no access token exists and you need to perform a login to get the wanted permissions. **Returns** - `string` - the authentication token or nil if the user is not logged in ### facebook.get_current_profile *Type:* FUNCTION iOS ONLY. Get the users [FBSDKProfile.currentProfile](https://developers.facebook.com/docs/facebook-login/limited-login/ios/). [Reading From Profile Helper Class](https://developers.facebook.com/docs/facebook-login/limited-login/permissions/profile-helper) **Returns** - `table` - After your application receives the logged-in user’s authentication token, you can use this function to read information that user has granted to your application. ### facebook.init *Type:* FUNCTION Initialize Facebook SDK (if facebook.autoinit is 0 in game.project) ### facebook.access_token *Type:* FUNCTION Get the current Facebook access token. This function returns the currently stored access token after a previous successful login. If it returns nil no access token exists and you need to perform a login to get the wanted permissions. **Returns** - `string` - the access token or nil if the user is not logged in **Examples** Get the current access token, then use it to perform a graph API request. ``` local function get_name_callback(self, id, response) -- do something with the response end function init(self) -- assuming we are already logged in. local token = facebook.access_token() if token then local url = "https://graph.facebook.com/me/?access_token=".. token http.request(url, "GET", get_name_callback) end end ``` ### facebook.permissions *Type:* FUNCTION Get the currently granted permissions. This function returns a table with all the currently granted permission strings. **Returns** - `table` - The permissions **Examples** Check the currently granted permissions for a particular permission ``` for _,permission in ipairs(facebook.permissions()) do if permission == "user_likes" then -- "user_likes" granted... break end end ``` ### facebook.post_event *Type:* FUNCTION Post an event to Facebook Analytics This function will post an event to Facebook Analytics where it can be used in the Facebook Insights system. **Parameters** - `event` (number | string) - An event can either be one of the predefined constants below or a text string which can be used to define a custom event that is registered with Facebook Analytics. - `facebook.EVENT_ACHIEVED_LEVEL` - `facebook.EVENT_ADDED_PAYMENT_INFO` - `facebook.EVENT_ADDED_TO_CART` - `facebook.EVENT_ADDED_TO_WISHLIST` - `facebook.EVENT_COMPLETED_REGISTRATION` - `facebook.EVENT_COMPLETED_TUTORIAL` - `facebook.EVENT_INITIATED_CHECKOUT` - `facebook.EVENT_PURCHASED` - `facebook.EVENT_RATED` - `facebook.EVENT_SEARCHED` - `facebook.EVENT_SPENT_CREDITS` - `facebook.EVENT_TIME_BETWEEN_SESSIONS` - `facebook.EVENT_UNLOCKED_ACHIEVEMENT` - `facebook.EVENT_VIEWED_CONTENT` - `value` (number) - A numeric value for the event. This should represent the value of the event, such as the level achieved, price for an item or number of orcs killed. - `params` (table) - Optional table with parameters and their values. A key in the table can either be one of the predefined constants below or a text which can be used to define a custom parameter. - `facebook.PARAM_CONTENT_ID` - `facebook.PARAM_CONTENT_TYPE` - `facebook.PARAM_CURRENCY` - `facebook.PARAM_DESCRIPTION` - `facebook.PARAM_LEVEL` - `facebook.PARAM_MAX_RATING_VALUE` - `facebook.PARAM_NUM_ITEMS` - `facebook.PARAM_PAYMENT_INFO_AVAILABLE` - `facebook.PARAM_REGISTRATION_METHOD` - `facebook.PARAM_SEARCH_STRING` - `facebook.PARAM_SOURCE_APPLICATION` - `facebook.PARAM_SUCCESS` **Examples** Post a spent credits event to Facebook Analytics ``` params = {[facebook.PARAM_LEVEL] = 30, [facebook.PARAM_NUM_ITEMS] = 2} facebook.post_event(facebook.EVENT_SPENT_CREDITS, 25, params) ``` ### facebook.enable_event_usage *Type:* FUNCTION Enable event usage with Facebook Analytics This function will enable event usage for Facebook Analytics which means that Facebook will be able to use event data for ad-tracking. [icon:attention] Event usage cannot be controlled and is always enabled for the Facebook Canvas platform, therefore this function has no effect on Facebook Canvas. ### facebook.disable_event_usage *Type:* FUNCTION Disable event usage with Facebook Analytics This function will disable event usage for Facebook Analytics which means that Facebook won't be able to use event data for ad-tracking. Events will still be sent to Facebook for insights. [icon:attention] Event usage cannot be controlled and is always enabled for the Facebook Canvas platform, therefore this function has no effect on Facebook Canvas. ### facebook.enable_advertiser_tracking *Type:* FUNCTION Enable advertiser tracking This function will set AdvertiserTrackingEnabled (the 'ATE' flag) to true on iOS, to inform Audience Network to use the data to deliver personalized ads for users on iOS 14 and above. ### facebook.disable_advertiser_tracking *Type:* FUNCTION Disable advertiser tracking This function will set AdvertiserTrackingEnabled (the 'ATE' flag) to false on iOS, to inform Audience Network not to use the data to deliver personalized ads for users on iOS 14 and above. ### facebook.show_dialog *Type:* FUNCTION Show facebook web dialog Display a Facebook web dialog of the type specified in the `dialog` parameter. The `param` table should be set up according to the requirements of each dialog type. Note that some parameters are mandatory. Below is the list of available dialogs and where to find Facebook's developer documentation on parameters and response data. `"apprequests"` Shows a Game Request dialog. Game Requests allows players to invite their friends to play a game. Available parameters - [type:string] `title` - [type:string] `message` - [type:number] `action_type` - [type:number] `filters` - [type:string] `data` - [type:string] `object_id` - [type:table] `suggestions` - [type:table] `recipients` - [type:string] `to` On success, the "result" table parameter passed to the callback function will include the following fields - [type:string] `request_id` - [type:table] `to` [Details for each parameter](https://developers.facebook.com/docs/games/services/gamerequests/v2.6#dialogparameters) `"feed"` The Feed Dialog allows people to publish individual stories to their timeline. - [type:string] `caption` - [type:string] `description` - [type:string] `picture` - [type:string] `link` - [type:table] `people_ids` - [type:string] `place_id` - [type:string] `ref` On success, the "result" table parameter passed to the callback function will include the following fields - [type:string] `post_id` [Details for each parameter](https://developers.facebook.com/docs/sharing/reference/feed-dialog/v2.6#params) `"appinvite"` The App Invite dialog is available only on iOS and Android. Note that the `url` parameter corresponds to the appLinkURL (iOS) and setAppLinkUrl (Android) properties. - [type:string] `url` - [type:string] `preview_image` [Details for each parameter](https://developers.facebook.com/docs/reference/ios/current/class/FBSDKAppInviteContent) **Parameters** - `dialog` (string) - Dialog to show - `"apprequests"` - `"feed"` - `"appinvite"` - `param` (table) - table with dialog parameters - `callback` (function) - Callback function that is called when the dialog is closed. - `self` (object) - The context of the calling script - `result` (table) - table with dialog specific results. See above. - `error` (table) - Error message. If there is no error, `error` is `nil`. **Examples** Show a dialog allowing the user to share a post to their timeline ``` local function fb_share(self, result, error) if error then -- something did not go right... else -- do something sensible end end function init(self) -- assuming we have logged in with publish permissions local param = { link = "http://www.mygame.com",picture="http://www.mygame.com/image.jpg" } facebook.show_dialog("feed", param, fb_share) end ``` ### facebook.get_version *Type:* FUNCTION Get the version of the Facebook SDK used by the extension. **Returns** - `string` - The Facebook SDK version ### facebook.deferred_deep_link *Type:* FUNCTION Allows receiving deferred deep link URL and parameters. [More info about Referred Deep Links](https://developers.facebook.com/docs/app-ads/deep-linking/) **Parameters** - `callback` (function) - Callback function that is called when information is ready. - `self` (object) - The context of the calling script - `result` (table) - table with a deferred deep link information - `ref` (string) - ref for this App Link. - `extras` (table) - the full set of arguments for this app link. Properties like target uri & ref are typically picked out of this set of arguments. - `target_url` (string) - target uri for this App Link. - `error` (table) - Error message. If there is no error, `error` is `nil`. **Examples** Show a dialog allowing the user to share a post to their timeline ``` local function deferred_deep_link_callback(self, result, error) if error then print(error.error) else pprint(result) end end function init(self) facebook.deferred_deep_link(deferred_deep_link_callback) end ``` ### STATE_OPEN *Type:* VARIABLE The Facebook login session is open ### STATE_CLOSED_LOGIN_FAILED *Type:* VARIABLE The Facebook login session has closed because login failed ### GAMEREQUEST_ACTIONTYPE_NONE *Type:* VARIABLE Game request action type "none" for "apprequests" dialog ### GAMEREQUEST_ACTIONTYPE_SEND *Type:* VARIABLE Game request action type "send" for "apprequests" dialog ### GAMEREQUEST_ACTIONTYPE_ASKFOR *Type:* VARIABLE Game request action type "askfor" for "apprequests" dialog ### GAMEREQUEST_ACTIONTYPE_TURN *Type:* VARIABLE Game request action type "turn" for "apprequests" dialog ### GAMEREQUEST_FILTER_NONE *Type:* VARIABLE Game request filter type "none" for "apprequests" dialog ### GAMEREQUEST_FILTER_APPUSERS *Type:* VARIABLE Game request filter type "app_users" for "apprequests" dialog ### GAMEREQUEST_FILTER_APPNONUSERS *Type:* VARIABLE Game request filter type "app_non_users" for "apprequests" dialog ### EVENT_ACHIEVED_LEVEL *Type:* VARIABLE Log this event when the user has achieved a level ### EVENT_ADDED_PAYMENT_INFO *Type:* VARIABLE Log this event when the user has entered their payment info ### EVENT_ADDED_TO_CART *Type:* VARIABLE Log this event when the user has added an item to their cart The value_to_sum passed to facebook.post_event should be the item's price. ### EVENT_ADDED_TO_WISHLIST *Type:* VARIABLE Log this event when the user has added an item to their wish list The value_to_sum passed to facebook.post_event should be the item's price. ### EVENT_COMPLETED_REGISTRATION *Type:* VARIABLE Log this event when a user has completed registration with the app ### EVENT_COMPLETED_TUTORIAL *Type:* VARIABLE Log this event when the user has completed a tutorial in the app ### EVENT_INITIATED_CHECKOUT *Type:* VARIABLE Log this event when the user has entered the checkout process The value_to_sum passed to facebook.post_event should be the total price in the cart. ### EVENT_PURCHASED *Type:* VARIABLE Log this event when the user has completed a purchase. The value_to_sum passed to facebook.post_event should be the numeric rating. ### EVENT_RATED *Type:* VARIABLE Log this event when the user has rated an item in the app ### EVENT_SEARCHED *Type:* VARIABLE Log this event when a user has performed a search within the app ### EVENT_SPENT_CREDITS *Type:* VARIABLE Log this event when the user has spent app credits The value_to_sum passed to facebook.post_event should be the number of credits spent. ### EVENT_TIME_BETWEEN_SESSIONS *Type:* VARIABLE Log this event when measuring the time between user sessions ### EVENT_UNLOCKED_ACHIEVEMENT *Type:* VARIABLE Log this event when the user has unlocked an achievement in the app ### EVENT_VIEWED_CONTENT *Type:* VARIABLE Log this event when a user has viewed a form of content in the app ### PARAM_CONTENT_ID *Type:* VARIABLE Parameter key used to specify an ID for the content being logged about The parameter key could be an EAN, article identifier, etc., depending on the nature of the app. ### PARAM_CONTENT_TYPE *Type:* VARIABLE Parameter key used to specify a generic content type/family for the logged event The key is an arbitrary type/family (e.g. "music", "photo", "video") depending on the nature of the app. ### PARAM_CURRENCY *Type:* VARIABLE Parameter key used to specify currency used with logged event Use a currency value key, e.g. "USD", "EUR", "GBP" etc. See See ISO-4217 for specific values. ### PARAM_DESCRIPTION *Type:* VARIABLE Parameter key used to specify a description appropriate to the event being logged Use this for app specific event description, for instance the name of the achievement unlocked in the facebook.EVENT_UNLOCKED_ACHIEVEMENT event. ### PARAM_LEVEL *Type:* VARIABLE Parameter key used to specify the level achieved ### PARAM_MAX_RATING_VALUE *Type:* VARIABLE Parameter key used to specify the maximum rating available Set to specify the max rating available for the facebook.EVENT_RATED event. E.g., "5" or "10". ### PARAM_NUM_ITEMS *Type:* VARIABLE Parameter key used to specify how many items are being processed Set to specify the number of items being processed for an facebook.EVENT_INITIATED_CHECKOUT or facebook.EVENT_PURCHASED event. ### PARAM_PAYMENT_INFO_AVAILABLE *Type:* VARIABLE Parameter key used to specify whether payment info is available Set to specify if payment info is available for the facebook.EVENT_INITIATED_CHECKOUT event. ### PARAM_REGISTRATION_METHOD *Type:* VARIABLE Parameter key used to specify method user has used to register for the app Set to specify what registation method a user used for the app, e.g. "Facebook", "email", "Twitter", etc. ### PARAM_SEARCH_STRING *Type:* VARIABLE Parameter key used to specify user search string Set this to the the string that the user provided for a search operation. ### PARAM_SOURCE_APPLICATION *Type:* VARIABLE Parameter key used to specify source application package ### PARAM_SUCCESS *Type:* VARIABLE Parameter key used to specify activity success Set this key to indicate whether the activity being logged about was successful or not. ### AUDIENCE_NONE *Type:* VARIABLE Publish permission to reach no audience ### AUDIENCE_ONLYME *Type:* VARIABLE Publish permission to reach only me (private to current user) ### AUDIENCE_FRIENDS *Type:* VARIABLE Publish permission to reach user friends ### AUDIENCE_EVERYONE *Type:* VARIABLE Publish permission to reach everyone ### LOGIN_TRACKING_LIMITED *Type:* VARIABLE Login tracking Limited ### LOGIN_TRACKING_ENABLED *Type:* VARIABLE Login tracking enabled # extension-firebase-analytics {#apis:extension-firebase-analytics_firebase} **Namespace:** `firebase` **Language:** Lua **Type:** Extension Functions and constants for interacting with Firebase ## API ### firebase.analytics.initialize *Type:* FUNCTION Initialise analytics ### firebase.analytics.set_callback *Type:* FUNCTION Sets a callback function for receiving events from the SDK. Call `firebase.analytics.set_callback(nil)` to remove callback **Parameters** - `callback` (function) - Callback function that is executed on any event in the SDK. - `self` (object) - The calling script instance - `message_id` (number) - One of message types: `firebase.analytics.MSG_ERROR` `firebase.analytics.MSG_INSTANCE_ID` - `message` (table) - A table holding the data - `error` (string) - The error message (if an error occurred or `nil` otherwise) - `instance_id` (string) - For message_id MSG_INSTANCE_ID or `nil` otherwise. ### firebase.analytics.log *Type:* FUNCTION Log an event without parameters. **Parameters** - `name` (string) - Event name ### firebase.analytics.log_string *Type:* FUNCTION Log an event with one string parameter. **Parameters** - `name` (string) - Event name - `PARAMeter_name` (string) - Parameter name - `PARAMeter_value` (string) - Parameter value ### firebase.analytics.log_int *Type:* FUNCTION Log an event with one integer parameter. **Parameters** - `name` (string) - Event name - `PARAMeter_name` (string) - Parameter name - `PARAMeter_value` (number) - Parameter value ### firebase.analytics.log_number *Type:* FUNCTION Log an event with one float parameter. **Parameters** - `name` (string) - Event name - `PARAMeter_name` (string) - Parameter name - `PARAMeter_value` (number) - Parameter value ### firebase.analytics.log_table *Type:* FUNCTION Log an event with table parameters. **Parameters** - `name` (string) - Event name - `parameters_table` (table) - Table with parameters (key-value pairs) ### firebase.analytics.set_default_event_params *Type:* FUNCTION Log an event with table parameters. **Parameters** - `default_params` (table) - Table with default parameters (key-value pairs) ### firebase.analytics.set_user_id *Type:* FUNCTION Sets the user ID property. **Parameters** - `user_id` (string) - User ID property ### firebase.analytics.set_user_property *Type:* FUNCTION Set a user property to the given value. **Parameters** - `name` (string) - User property name - `property` (string) - User property value ### firebase.analytics.reset *Type:* FUNCTION Clears all data for this app from the device and resets the app instance id. ### firebase.analytics.get_id *Type:* FUNCTION Get the instance ID from the service. Returned in callback with MSG_INSTANCE_ID message_id. ### firebase.analytics.set_enabled *Type:* FUNCTION Sets whether analytics collection is enabled for this app on this device. **Parameters** - `key` (boolean) - The value ### MSG_ERROR *Type:* VARIABLE Event generated when an error occurred. ### MSG_INSTANCE_ID *Type:* VARIABLE Event generated when instance_id ready after `firebase.analytics.get_id()` call ### EVENT_ADIMPRESSION *Type:* STRING Predefined event ### EVENT_ADDPAYMENTINFO *Type:* STRING Predefined event ### EVENT_ADDSHIPPINGINFO *Type:* STRING Predefined event ### EVENT_ADDTOCART *Type:* STRING Predefined event ### EVENT_ADDTOWISHLIST *Type:* STRING Predefined event ### EVENT_APPOPEN *Type:* STRING Predefined event ### EVENT_BEGINCHECKOUT *Type:* STRING Predefined event ### EVENT_CAMPAIGNDETAILS *Type:* STRING Predefined event ### EVENT_EARNVIRTUALCURRENCY *Type:* STRING Predefined event ### EVENT_GENERATELEAD *Type:* STRING Predefined event ### EVENT_JOINGROUP *Type:* STRING Predefined event ### EVENT_LEVELEND *Type:* STRING Predefined event ### EVENT_LEVELSTART *Type:* STRING Predefined event ### EVENT_LEVELUP *Type:* STRING Predefined event ### EVENT_LOGIN *Type:* STRING Predefined event ### EVENT_POSTSCORE *Type:* STRING Predefined event ### EVENT_PURCHASE *Type:* STRING Predefined event ### EVENT_REFUND *Type:* STRING Predefined event ### EVENT_REMOVEFROMCART *Type:* STRING Predefined event ### EVENT_SCREENVIEW *Type:* STRING Predefined event ### EVENT_SEARCH *Type:* STRING Predefined event ### EVENT_SELECTCONTENT *Type:* STRING Predefined event ### EVENT_SELECTITEM *Type:* STRING Predefined event ### EVENT_SELECTPROMOTION *Type:* STRING Predefined event ### EVENT_SHARE *Type:* STRING Predefined event ### EVENT_SIGNUP *Type:* STRING Predefined event ### EVENT_SPENDVIRTUALCURRENCY *Type:* STRING Predefined event ### EVENT_TUTORIALBEGIN *Type:* STRING Predefined event ### EVENT_TUTORIALCOMPLETE *Type:* STRING Predefined event ### EVENT_UNLOCKACHIEVEMENT *Type:* STRING Predefined event ### EVENT_VIEWCART *Type:* STRING Predefined event ### EVENT_VIEWITEM *Type:* STRING Predefined event ### EVENT_VIEWITEMLIST *Type:* STRING Predefined event ### EVENT_VIEWPROMOTION *Type:* STRING Predefined event ### EVENT_VIEWSEARCHRESULTS *Type:* STRING Predefined event ### PARAM_ADFORMAT *Type:* STRING Predefined parameter ### PARAM_ADNETWORKCLICKID *Type:* STRING Predefined parameter ### PARAM_ADPLATFORM *Type:* STRING Predefined parameter ### PARAM_ADSOURCE *Type:* STRING Predefined parameter ### PARAM_ADUNITNAME *Type:* STRING Predefined parameter ### PARAM_AFFILIATION *Type:* STRING Predefined parameter ### PARAM_CP1 *Type:* STRING Predefined parameter ### PARAM_CAMPAIGN *Type:* STRING Predefined parameter ### PARAM_CAMPAIGNID *Type:* STRING Predefined parameter ### PARAM_CHARACTER *Type:* STRING Predefined parameter ### PARAM_CONTENT *Type:* STRING Predefined parameter ### PARAM_CONTENTTYPE *Type:* STRING Predefined parameter ### PARAM_COUPON *Type:* STRING Predefined parameter ### PARAM_CREATIVEFORMAT *Type:* STRING Predefined parameter ### PARAM_CREATIVENAME *Type:* STRING Predefined parameter ### PARAM_CREATIVESLOT *Type:* STRING Predefined parameter ### PARAM_CURRENCY *Type:* STRING Predefined parameter ### PARAM_DESTINATION *Type:* STRING Predefined parameter ### PARAM_DISCOUNT *Type:* STRING Predefined parameter ### PARAM_ENDDATE *Type:* STRING Predefined parameter ### PARAM_EXTENDSESSION *Type:* STRING Predefined parameter ### PARAM_FLIGHTNUMBER *Type:* STRING Predefined parameter ### PARAM_GROUPID *Type:* STRING Predefined parameter ### PARAM_INDEX *Type:* STRING Predefined parameter ### PARAM_ITEMBRAND *Type:* STRING Predefined parameter ### PARAM_ITEMCATEGORY *Type:* STRING Predefined parameter ### PARAM_ITEMCATEGORY2 *Type:* STRING Predefined parameter ### PARAM_ITEMCATEGORY3 *Type:* STRING Predefined parameter ### PARAM_ITEMCATEGORY4 *Type:* STRING Predefined parameter ### PARAM_ITEMCATEGORY5 *Type:* STRING Predefined parameter ### PARAM_ITEMID *Type:* STRING Predefined parameter ### PARAM_ITEMLISTID *Type:* STRING Predefined parameter ### PARAM_ITEMLISTNAME *Type:* STRING Predefined parameter ### PARAM_ITEMNAME *Type:* STRING Predefined parameter ### PARAM_ITEMVARIANT *Type:* STRING Predefined parameter ### PARAM_ITEMS *Type:* STRING Predefined parameter ### PARAM_LEVEL *Type:* STRING Predefined parameter ### PARAM_LEVELNAME *Type:* STRING Predefined parameter ### PARAM_LOCATION *Type:* STRING Predefined parameter ### PARAM_LOCATIONID *Type:* STRING Predefined parameter ### PARAM_MARKETINGTACTIC *Type:* STRING Predefined parameter ### PARAM_MEDIUM *Type:* STRING Predefined parameter ### PARAM_METHOD *Type:* STRING Predefined parameter ### PARAM_NUMBEROFNIGHTS *Type:* STRING Predefined parameter ### PARAM_NUMBEROFPASSENGERS *Type:* STRING Predefined parameter ### PARAM_NUMBEROFROOMS *Type:* STRING Predefined parameter ### PARAM_ORIGIN *Type:* STRING Predefined parameter ### PARAM_PAYMENTTYPE *Type:* STRING Predefined parameter ### PARAM_PRICE *Type:* STRING Predefined parameter ### PARAM_PROMOTIONID *Type:* STRING Predefined parameter ### PARAM_PROMOTIONNAME *Type:* STRING Predefined parameter ### PARAM_QUANTITY *Type:* STRING Predefined parameter ### PARAM_SCORE *Type:* STRING Predefined parameter ### PARAM_SCREENCLASS *Type:* STRING Predefined parameter ### PARAM_SCREENNAME *Type:* STRING Predefined parameter ### PARAM_SEARCHTERM *Type:* STRING Predefined parameter ### PARAM_SHIPPING *Type:* STRING Predefined parameter ### PARAM_SHIPPINGTIER *Type:* STRING Predefined parameter ### PARAM_SOURCE *Type:* STRING Predefined parameter ### PARAM_SOURCEPLATFORM *Type:* STRING Predefined parameter ### PARAM_STARTDATE *Type:* STRING Predefined parameter ### PARAM_SUCCESS *Type:* STRING Predefined parameter ### PARAM_TAX *Type:* STRING Predefined parameter ### PARAM_TERM *Type:* STRING Predefined parameter ### PARAM_TRANSACTIONID *Type:* STRING Predefined parameter ### PARAM_TRAVELCLASS *Type:* STRING Predefined parameter ### PARAM_VALUE *Type:* STRING Predefined parameter ### PARAM_VIRTUALCURRENCYNAME *Type:* STRING Predefined parameter ### PROP_ALLOWADPERSONALIZATIONSIGNALS *Type:* STRING Predefined property ### PROP_SIGNUPMETHOD *Type:* STRING Predefined property ### *Type:* TABLE Functions and constants for interacting with Firebase Analytics # extension-firebase-remoteconfig {#apis:extension-firebase-remoteconfig_firebase} **Namespace:** `firebase` **Language:** Lua **Type:** Extension Functions and constants for interacting with Firebase ## API ### firebase.remoteconfig.initialize *Type:* FUNCTION Initialise Firebase Remote Config. Generates MSG_INITIALIZED or MSG_ERROR ### firebase.remoteconfig.set_callback *Type:* FUNCTION Sets a callback function for receiving events from the SDK. Call `firebase.set_callback(nil)` to remove callback **Parameters** - `callback` (function) - Callback function that is executed on any event in the SDK. - `self` (object) - The calling script instance - `message_id` (number) - One of message types: `firebase.remoteconfig.MSG_INITIALIZED` `firebase.remoteconfig.MSG_INSTALLATION_AUTH_TOKEN` `firebase.remoteconfig.MSG_INSTALLATION_ID` `firebase.remoteconfig.MSG_DEFAULTS_SET` `firebase.remoteconfig.MSG_FETCHED` `firebase.remoteconfig.MSG_ACTIVATED` `firebase.remoteconfig.MSG_SETTINGS_UPDATED` `firebase.remoteconfig.MSG_ERROR` - `message` (table) - A table holding the data - `error` (string) - The error message (if an error occurred or `nil` otherwise) ### firebase.remoteconfig.fetch *Type:* FUNCTION Fetches config data from the server. Generates MSG_FETCHED or MSG_ERROR ### firebase.remoteconfig.activate *Type:* FUNCTION Asynchronously activates the most recently fetched configs, so that the fetched key value pairs take effect. Generates MSG_ACTIVATED or MSG_ERROR ### firebase.remoteconfig.fetch_and_activate *Type:* FUNCTION Asynchronously fetches and then activates the fetched configs. Generates MSG_FETCHED and MSG_ACTIVATED or MSG_ERROR ### firebase.remoteconfig.get_boolean *Type:* FUNCTION Returns the value associated with a key, converted to a bool. **Parameters** - `key` (string) - Key of the value to be retrieved ### firebase.remoteconfig.get_data *Type:* FUNCTION Returns the value associated with a key, as a vector of raw byte-data. **Parameters** - `key` (string) - Key of the value to be retrieved ### firebase.remoteconfig.get_number *Type:* FUNCTION Returns the value associated with a key, converted to a double. **Parameters** - `key` (string) - Key of the value to be retrieved ### firebase.remoteconfig.get_string *Type:* FUNCTION Returns the value associated with a key, converted to a string. **Parameters** - `key` (string) - Key of the value to be retrieved ### firebase.remoteconfig.get_keys *Type:* FUNCTION Gets the set of all keys. ### firebase.remoteconfig.set_defaults *Type:* FUNCTION Sets the default values. **Parameters** - `defaults` (table) - Key-value pairs representing the default values. Generates MSG_DEFAULTS_SET or MSG_ERROR ### firebase.remoteconfig.set_minimum_fetch_interval *Type:* FUNCTION Sets the minimum fetch interval. **Parameters** - `minimum_fetch_interval` (int) - The minimum interval in milliseconds between successive fetch calls. Generates MSG_SETTINGS_UPDATED or MSG_ERROR ### firebase.remoteconfig.set_timeout *Type:* FUNCTION Sets the timeout that specifies how long the client should wait for a connection to the Firebase Remote Config servers **Parameters** - `minimum_fetch_interval` (int) - The timeout interval in milliseconds. Generates MSG_SETTINGS_UPDATED or MSG_ERROR ### MSG_INITIALIZED *Type:* VARIABLE Event generated when remote config has been initialized and is ready for use ### MSG_ERROR *Type:* VARIABLE Event generated when an error occurred. ### MSG_DEFAULTS_SET *Type:* VARIABLE Event generated when the default values have been set ### MSG_FETCHED *Type:* VARIABLE Event generated when the remote config has been fetched ### MSG_ACTIVATED *Type:* VARIABLE Event generated when the remote config has been activated ### MSG_SETTINGS_UPDATED *Type:* VARIABLE Event generated when remote config settings have been updated ### *Type:* TABLE Functions and constants for interacting with Firebase Remote Config # extension-firebase {#apis:extension-firebase_firebase} **Namespace:** `firebase` **Language:** Lua **Type:** Extension Functions and constants for interacting with Firebase ## API ### firebase.initialize *Type:* FUNCTION Initialise Firebase **Parameters** - `options` (table) - Optional table with initialisation parameters to use instead of those specified in google-services.xml/plist When passing this, disable creation of the default Firebase App by specifying firebase.no_auto_init in game.project Valid keys in the table are api_key, app_id, database_url, messaging_sender_id, project_id, storage_bucket. All values are strings. ### firebase.get_installation_auth_token *Type:* FUNCTION Get the Firebase Installation auth token ### firebase.set_callback *Type:* FUNCTION Sets a callback function for receiving events from the SDK. Call `firebase.set_callback(nil)` to remove callback **Parameters** - `callback` (function) - Callback function that is executed on any event in the SDK. - `self` (object) - The calling script instance - `message_id` (number) - One of message types: `firebase.MSG_INITIALIZED` `firebase.MSG_INSTALLATION_AUTH_TOKEN` `firebase.MSG_INSTALLATION_ID` `firebase.MSG_ERROR` - `message` (table) - A table holding the data - `token` (number) - for MSG_INSTALLATION_AUTH_TOKEN - `id` (number) - for MSG_INSTALLATION_ID - `error` (string) - The error message (if an error occurred or `nil` otherwise) ### firebase.get_installation_id *Type:* FUNCTION Get the Firebase Installation id ### MSG_ERROR *Type:* VARIABLE ### MSG_INITIALIZED *Type:* VARIABLE ### MSG_INSTALLATION_AUTH_TOKEN *Type:* VARIABLE ### MSG_INSTALLATION_ID *Type:* VARIABLE # extension-fmod {#apis:extension-fmod_fmod} **Namespace:** `fmod` **Language:** Lua **Type:** Extension FMOD Low Level API for audio playback and manipulation. This module provides access to FMOD's low-level audio engine, allowing you to: - Create and play sounds - Control audio channels and channel groups - Apply DSP effects - Handle 3D audio positioning For more information, see the [FMOD documentation](https://www.fmod.com/docs). ## API ### THREAD_TYPE_MIXER *Type:* VARIABLE Thread type - mixer. ### THREAD_TYPE_FEEDER *Type:* VARIABLE Thread type - feeder. ### THREAD_TYPE_STREAM *Type:* VARIABLE Thread type - stream. ### THREAD_TYPE_FILE *Type:* VARIABLE Thread type - file. ### THREAD_TYPE_NONBLOCKING *Type:* VARIABLE Thread type - nonblocking. ### THREAD_TYPE_RECORD *Type:* VARIABLE Thread type - record. ### THREAD_TYPE_GEOMETRY *Type:* VARIABLE Thread type - geometry. ### THREAD_TYPE_PROFILER *Type:* VARIABLE Thread type - profiler. ### THREAD_TYPE_STUDIO_UPDATE *Type:* VARIABLE Thread type - studio update. ### THREAD_TYPE_STUDIO_LOAD_BANK *Type:* VARIABLE Thread type - studio load bank. ### THREAD_TYPE_STUDIO_LOAD_SAMPLE *Type:* VARIABLE Thread type - studio load sample. ### THREAD_TYPE_CONVOLUTION1 *Type:* VARIABLE Thread type - convolution1. ### THREAD_TYPE_CONVOLUTION2 *Type:* VARIABLE Thread type - convolution2. ### OK *Type:* VARIABLE Operation completed successfully. ### ERR_BADCOMMAND *Type:* VARIABLE Error - badcommand. ### ERR_CHANNEL_ALLOC *Type:* VARIABLE Error - channel alloc. ### ERR_CHANNEL_STOLEN *Type:* VARIABLE Error - channel stolen. ### ERR_DMA *Type:* VARIABLE Error - dma. ### ERR_DSP_CONNECTION *Type:* VARIABLE Error - dsp connection. ### ERR_DSP_DONTPROCESS *Type:* VARIABLE Error - dsp dontprocess. ### ERR_DSP_FORMAT *Type:* VARIABLE Error - dsp format. ### ERR_DSP_INUSE *Type:* VARIABLE Error - dsp inuse. ### ERR_DSP_NOTFOUND *Type:* VARIABLE Error - dsp notfound. ### ERR_DSP_RESERVED *Type:* VARIABLE Error - dsp reserved. ### ERR_DSP_SILENCE *Type:* VARIABLE Error - dsp silence. ### ERR_DSP_TYPE *Type:* VARIABLE Error - dsp type. ### ERR_FILE_BAD *Type:* VARIABLE Error - file bad. ### ERR_FILE_COULDNOTSEEK *Type:* VARIABLE Error - file couldnotseek. ### ERR_FILE_DISKEJECTED *Type:* VARIABLE Error - file diskejected. ### ERR_FILE_EOF *Type:* VARIABLE Error - file eof. ### ERR_FILE_ENDOFDATA *Type:* VARIABLE Error - file endofdata. ### ERR_FILE_NOTFOUND *Type:* VARIABLE Error - file notfound. ### ERR_FORMAT *Type:* VARIABLE Error - format. ### ERR_HEADER_MISMATCH *Type:* VARIABLE Error - header mismatch. ### ERR_HTTP *Type:* VARIABLE Error - http. ### ERR_HTTP_ACCESS *Type:* VARIABLE Error - http access. ### ERR_HTTP_PROXY_AUTH *Type:* VARIABLE Error - http proxy auth. ### ERR_HTTP_SERVER_ERROR *Type:* VARIABLE Error - http server error. ### ERR_HTTP_TIMEOUT *Type:* VARIABLE Error - http timeout. ### ERR_INITIALIZATION *Type:* VARIABLE Error - initialization. ### ERR_INITIALIZED *Type:* VARIABLE Error - initialized. ### ERR_INTERNAL *Type:* VARIABLE Error - internal. ### ERR_INVALID_FLOAT *Type:* VARIABLE Error - invalid float. ### ERR_INVALID_HANDLE *Type:* VARIABLE Error - invalid handle. ### ERR_INVALID_PARAM *Type:* VARIABLE Error - invalid param. ### ERR_INVALID_POSITION *Type:* VARIABLE Error - invalid position. ### ERR_INVALID_SPEAKER *Type:* VARIABLE Error - invalid speaker. ### ERR_INVALID_SYNCPOINT *Type:* VARIABLE Error - invalid syncpoint. ### ERR_INVALID_THREAD *Type:* VARIABLE Error - invalid thread. ### ERR_INVALID_VECTOR *Type:* VARIABLE Error - invalid vector. ### ERR_MAXAUDIBLE *Type:* VARIABLE Error - maxaudible. ### ERR_MEMORY *Type:* VARIABLE Error - memory. ### ERR_MEMORY_CANTPOINT *Type:* VARIABLE Error - memory cantpoint. ### ERR_NEEDS3D *Type:* VARIABLE Error - needs3d. ### ERR_NEEDSHARDWARE *Type:* VARIABLE Error - needshardware. ### ERR_NET_CONNECT *Type:* VARIABLE Error - net connect. ### ERR_NET_SOCKET_ERROR *Type:* VARIABLE Error - net socket error. ### ERR_NET_URL *Type:* VARIABLE Error - net url. ### ERR_NET_WOULD_BLOCK *Type:* VARIABLE Error - net would block. ### ERR_NOTREADY *Type:* VARIABLE Error - notready. ### ERR_OUTPUT_ALLOCATED *Type:* VARIABLE Error - output allocated. ### ERR_OUTPUT_CREATEBUFFER *Type:* VARIABLE Error - output createbuffer. ### ERR_OUTPUT_DRIVERCALL *Type:* VARIABLE Error - output drivercall. ### ERR_OUTPUT_FORMAT *Type:* VARIABLE Error - output format. ### ERR_OUTPUT_INIT *Type:* VARIABLE Error - output init. ### ERR_OUTPUT_NODRIVERS *Type:* VARIABLE Error - output nodrivers. ### ERR_PLUGIN *Type:* VARIABLE Error - plugin. ### ERR_PLUGIN_MISSING *Type:* VARIABLE Error - plugin missing. ### ERR_PLUGIN_RESOURCE *Type:* VARIABLE Error - plugin resource. ### ERR_PLUGIN_VERSION *Type:* VARIABLE Error - plugin version. ### ERR_RECORD *Type:* VARIABLE Error - record. ### ERR_REVERB_CHANNELGROUP *Type:* VARIABLE Error - reverb channelgroup. ### ERR_REVERB_INSTANCE *Type:* VARIABLE Error - reverb instance. ### ERR_SUBSOUNDS *Type:* VARIABLE Error - subsounds. ### ERR_SUBSOUND_ALLOCATED *Type:* VARIABLE Error - subsound allocated. ### ERR_SUBSOUND_CANTMOVE *Type:* VARIABLE Error - subsound cantmove. ### ERR_TAGNOTFOUND *Type:* VARIABLE Error - tagnotfound. ### ERR_TOOMANYCHANNELS *Type:* VARIABLE Error - toomanychannels. ### ERR_TRUNCATED *Type:* VARIABLE Error - truncated. ### ERR_UNIMPLEMENTED *Type:* VARIABLE Error - unimplemented. ### ERR_UNINITIALIZED *Type:* VARIABLE Error - uninitialized. ### ERR_UNSUPPORTED *Type:* VARIABLE Error - unsupported. ### ERR_VERSION *Type:* VARIABLE Error - version. ### ERR_EVENT_ALREADY_LOADED *Type:* VARIABLE Error - event already loaded. ### ERR_EVENT_LIVEUPDATE_BUSY *Type:* VARIABLE Error - event liveupdate busy. ### ERR_EVENT_LIVEUPDATE_MISMATCH *Type:* VARIABLE Error - event liveupdate mismatch. ### ERR_EVENT_LIVEUPDATE_TIMEOUT *Type:* VARIABLE Error - event liveupdate timeout. ### ERR_EVENT_NOTFOUND *Type:* VARIABLE Error - event notfound. ### ERR_STUDIO_UNINITIALIZED *Type:* VARIABLE Error - studio uninitialized. ### ERR_STUDIO_NOT_LOADED *Type:* VARIABLE Error - studio not loaded. ### ERR_INVALID_STRING *Type:* VARIABLE Error - invalid string. ### ERR_ALREADY_LOCKED *Type:* VARIABLE Error - already locked. ### ERR_NOT_LOCKED *Type:* VARIABLE Error - not locked. ### ERR_RECORD_DISCONNECTED *Type:* VARIABLE Error - record disconnected. ### ERR_TOOMANYSAMPLES *Type:* VARIABLE Error - toomanysamples. ### CHANNELCONTROL_CHANNEL *Type:* VARIABLE Channel control type - channel. ### CHANNELCONTROL_CHANNELGROUP *Type:* VARIABLE Channel control type - channelgroup. ### OUTPUTTYPE_AUTODETECT *Type:* VARIABLE Output type - autodetect. ### OUTPUTTYPE_UNKNOWN *Type:* VARIABLE Output type - unknown. ### OUTPUTTYPE_NOSOUND *Type:* VARIABLE Output type - nosound. ### OUTPUTTYPE_WAVWRITER *Type:* VARIABLE Output type - wavwriter. ### OUTPUTTYPE_NOSOUND_NRT *Type:* VARIABLE Output type - nosound nrt. ### OUTPUTTYPE_WAVWRITER_NRT *Type:* VARIABLE Output type - wavwriter nrt. ### OUTPUTTYPE_WASAPI *Type:* VARIABLE Output type - wasapi. ### OUTPUTTYPE_ASIO *Type:* VARIABLE Output type - asio. ### OUTPUTTYPE_PULSEAUDIO *Type:* VARIABLE Output type - pulseaudio. ### OUTPUTTYPE_ALSA *Type:* VARIABLE Output type - alsa. ### OUTPUTTYPE_COREAUDIO *Type:* VARIABLE Output type - coreaudio. ### OUTPUTTYPE_AUDIOTRACK *Type:* VARIABLE Output type - audiotrack. ### OUTPUTTYPE_OPENSL *Type:* VARIABLE Output type - opensl. ### OUTPUTTYPE_AUDIOOUT *Type:* VARIABLE Output type - audioout. ### OUTPUTTYPE_AUDIO3D *Type:* VARIABLE Output type - audio3d. ### OUTPUTTYPE_WEBAUDIO *Type:* VARIABLE Output type - webaudio. ### OUTPUTTYPE_NNAUDIO *Type:* VARIABLE Output type - nnaudio. ### OUTPUTTYPE_WINSONIC *Type:* VARIABLE Output type - winsonic. ### OUTPUTTYPE_AAUDIO *Type:* VARIABLE Output type - aaudio. ### OUTPUTTYPE_AUDIOWORKLET *Type:* VARIABLE Output type - audioworklet. ### OUTPUTTYPE_PHASE *Type:* VARIABLE Output type - phase. ### OUTPUTTYPE_OHAUDIO *Type:* VARIABLE Output type - ohaudio. ### DEBUG_MODE_TTY *Type:* VARIABLE Debug mode - tty. ### DEBUG_MODE_FILE *Type:* VARIABLE Debug mode - file. ### DEBUG_MODE_CALLBACK *Type:* VARIABLE Debug mode - callback. ### SPEAKERMODE_DEFAULT *Type:* VARIABLE Speaker mode - default. ### SPEAKERMODE_RAW *Type:* VARIABLE Speaker mode - raw. ### SPEAKERMODE_MONO *Type:* VARIABLE Speaker mode - mono. ### SPEAKERMODE_STEREO *Type:* VARIABLE Speaker mode - stereo. ### SPEAKERMODE_QUAD *Type:* VARIABLE Speaker mode - quad. ### SPEAKERMODE_SURROUND *Type:* VARIABLE Speaker mode - surround. ### SPEAKERMODE_5POINT1 *Type:* VARIABLE Speaker mode - 5point1. ### SPEAKERMODE_7POINT1 *Type:* VARIABLE Speaker mode - 7point1. ### SPEAKERMODE_7POINT1POINT4 *Type:* VARIABLE Speaker mode - 7point1point4. ### SPEAKER_NONE *Type:* VARIABLE Speaker position - none. ### SPEAKER_FRONT_LEFT *Type:* VARIABLE Speaker position - front left. ### SPEAKER_FRONT_RIGHT *Type:* VARIABLE Speaker position - front right. ### SPEAKER_FRONT_CENTER *Type:* VARIABLE Speaker position - front center. ### SPEAKER_LOW_FREQUENCY *Type:* VARIABLE Speaker position - low frequency. ### SPEAKER_SURROUND_LEFT *Type:* VARIABLE Speaker position - surround left. ### SPEAKER_SURROUND_RIGHT *Type:* VARIABLE Speaker position - surround right. ### SPEAKER_BACK_LEFT *Type:* VARIABLE Speaker position - back left. ### SPEAKER_BACK_RIGHT *Type:* VARIABLE Speaker position - back right. ### SPEAKER_TOP_FRONT_LEFT *Type:* VARIABLE Speaker position - top front left. ### SPEAKER_TOP_FRONT_RIGHT *Type:* VARIABLE Speaker position - top front right. ### SPEAKER_TOP_BACK_LEFT *Type:* VARIABLE Speaker position - top back left. ### SPEAKER_TOP_BACK_RIGHT *Type:* VARIABLE Speaker position - top back right. ### CHANNELORDER_DEFAULT *Type:* VARIABLE Channel order - default. ### CHANNELORDER_WAVEFORMAT *Type:* VARIABLE Channel order - waveformat. ### CHANNELORDER_PROTOOLS *Type:* VARIABLE Channel order - protools. ### CHANNELORDER_ALLMONO *Type:* VARIABLE Channel order - allmono. ### CHANNELORDER_ALLSTEREO *Type:* VARIABLE Channel order - allstereo. ### CHANNELORDER_ALSA *Type:* VARIABLE Channel order - alsa. ### PLUGINTYPE_OUTPUT *Type:* VARIABLE Plugin type - output. ### PLUGINTYPE_CODEC *Type:* VARIABLE Plugin type - codec. ### PLUGINTYPE_DSP *Type:* VARIABLE Plugin type - dsp. ### SOUND_TYPE_UNKNOWN *Type:* VARIABLE Sound file type - unknown. ### SOUND_TYPE_AIFF *Type:* VARIABLE Sound file type - aiff. ### SOUND_TYPE_ASF *Type:* VARIABLE Sound file type - asf. ### SOUND_TYPE_DLS *Type:* VARIABLE Sound file type - dls. ### SOUND_TYPE_FLAC *Type:* VARIABLE Sound file type - flac. ### SOUND_TYPE_FSB *Type:* VARIABLE Sound file type - fsb. ### SOUND_TYPE_IT *Type:* VARIABLE Sound file type - it. ### SOUND_TYPE_MIDI *Type:* VARIABLE Sound file type - midi. ### SOUND_TYPE_MOD *Type:* VARIABLE Sound file type - mod. ### SOUND_TYPE_MPEG *Type:* VARIABLE Sound file type - mpeg. ### SOUND_TYPE_OGGVORBIS *Type:* VARIABLE Sound file type - oggvorbis. ### SOUND_TYPE_PLAYLIST *Type:* VARIABLE Sound file type - playlist. ### SOUND_TYPE_RAW *Type:* VARIABLE Sound file type - raw. ### SOUND_TYPE_S3M *Type:* VARIABLE Sound file type - s3m. ### SOUND_TYPE_USER *Type:* VARIABLE Sound file type - user. ### SOUND_TYPE_WAV *Type:* VARIABLE Sound file type - wav. ### SOUND_TYPE_XM *Type:* VARIABLE Sound file type - xm. ### SOUND_TYPE_XMA *Type:* VARIABLE Sound file type - xma. ### SOUND_TYPE_AUDIOQUEUE *Type:* VARIABLE Sound file type - audioqueue. ### SOUND_TYPE_AT9 *Type:* VARIABLE Sound file type - at9. ### SOUND_TYPE_VORBIS *Type:* VARIABLE Sound file type - vorbis. ### SOUND_TYPE_MEDIA_FOUNDATION *Type:* VARIABLE Sound file type - media foundation. ### SOUND_TYPE_MEDIACODEC *Type:* VARIABLE Sound file type - mediacodec. ### SOUND_TYPE_FADPCM *Type:* VARIABLE Sound file type - fadpcm. ### SOUND_TYPE_OPUS *Type:* VARIABLE Sound file type - opus. ### SOUND_FORMAT_NONE *Type:* VARIABLE Sound data format - none. ### SOUND_FORMAT_PCM8 *Type:* VARIABLE Sound data format - pcm8. ### SOUND_FORMAT_PCM16 *Type:* VARIABLE Sound data format - pcm16. ### SOUND_FORMAT_PCM24 *Type:* VARIABLE Sound data format - pcm24. ### SOUND_FORMAT_PCM32 *Type:* VARIABLE Sound data format - pcm32. ### SOUND_FORMAT_PCMFLOAT *Type:* VARIABLE Sound data format - pcmfloat. ### SOUND_FORMAT_BITSTREAM *Type:* VARIABLE Sound data format - bitstream. ### OPENSTATE_READY *Type:* VARIABLE Open state - ready. ### OPENSTATE_LOADING *Type:* VARIABLE Open state - loading. ### OPENSTATE_ERROR *Type:* VARIABLE Open state - error. ### OPENSTATE_CONNECTING *Type:* VARIABLE Open state - connecting. ### OPENSTATE_BUFFERING *Type:* VARIABLE Open state - buffering. ### OPENSTATE_SEEKING *Type:* VARIABLE Open state - seeking. ### OPENSTATE_PLAYING *Type:* VARIABLE Open state - playing. ### OPENSTATE_SETPOSITION *Type:* VARIABLE Open state - setposition. ### SOUNDGROUP_BEHAVIOR_FAIL *Type:* VARIABLE Sound group behavior - fail. ### SOUNDGROUP_BEHAVIOR_MUTE *Type:* VARIABLE Sound group behavior - mute. ### SOUNDGROUP_BEHAVIOR_STEALLOWEST *Type:* VARIABLE Sound group behavior - steallowest. ### CHANNELCONTROL_CALLBACK_END *Type:* VARIABLE Channel control callback - end. ### CHANNELCONTROL_CALLBACK_VIRTUALVOICE *Type:* VARIABLE Channel control callback - virtualvoice. ### CHANNELCONTROL_CALLBACK_SYNCPOINT *Type:* VARIABLE Channel control callback - syncpoint. ### CHANNELCONTROL_CALLBACK_OCCLUSION *Type:* VARIABLE Channel control callback - occlusion. ### CHANNELCONTROL_DSP_HEAD *Type:* VARIABLE Channel control type - dsp head. ### CHANNELCONTROL_DSP_FADER *Type:* VARIABLE Channel control type - dsp fader. ### CHANNELCONTROL_DSP_TAIL *Type:* VARIABLE Channel control type - dsp tail. ### ERRORCALLBACK_INSTANCETYPE_NONE *Type:* VARIABLE Errorcallback instancetype none. ### ERRORCALLBACK_INSTANCETYPE_SYSTEM *Type:* VARIABLE Errorcallback instancetype system. ### ERRORCALLBACK_INSTANCETYPE_CHANNEL *Type:* VARIABLE Errorcallback instancetype channel. ### ERRORCALLBACK_INSTANCETYPE_CHANNELGROUP *Type:* VARIABLE Errorcallback instancetype channelgroup. ### ERRORCALLBACK_INSTANCETYPE_CHANNELCONTROL *Type:* VARIABLE Errorcallback instancetype channelcontrol. ### ERRORCALLBACK_INSTANCETYPE_SOUND *Type:* VARIABLE Errorcallback instancetype sound. ### ERRORCALLBACK_INSTANCETYPE_SOUNDGROUP *Type:* VARIABLE Errorcallback instancetype soundgroup. ### ERRORCALLBACK_INSTANCETYPE_DSP *Type:* VARIABLE Errorcallback instancetype dsp. ### ERRORCALLBACK_INSTANCETYPE_DSPCONNECTION *Type:* VARIABLE Errorcallback instancetype dspconnection. ### ERRORCALLBACK_INSTANCETYPE_GEOMETRY *Type:* VARIABLE Errorcallback instancetype geometry. ### ERRORCALLBACK_INSTANCETYPE_REVERB3D *Type:* VARIABLE Errorcallback instancetype reverb3d. ### ERRORCALLBACK_INSTANCETYPE_STUDIO_SYSTEM *Type:* VARIABLE Errorcallback instancetype studio system. ### ERRORCALLBACK_INSTANCETYPE_STUDIO_EVENTDESCRIPTION *Type:* VARIABLE Errorcallback instancetype studio eventdescription. ### ERRORCALLBACK_INSTANCETYPE_STUDIO_EVENTINSTANCE *Type:* VARIABLE Errorcallback instancetype studio eventinstance. ### ERRORCALLBACK_INSTANCETYPE_STUDIO_PARAMETERINSTANCE *Type:* VARIABLE Errorcallback instancetype studio parameterinstance. ### ERRORCALLBACK_INSTANCETYPE_STUDIO_BUS *Type:* VARIABLE Errorcallback instancetype studio bus. ### ERRORCALLBACK_INSTANCETYPE_STUDIO_VCA *Type:* VARIABLE Errorcallback instancetype studio vca. ### ERRORCALLBACK_INSTANCETYPE_STUDIO_BANK *Type:* VARIABLE Errorcallback instancetype studio bank. ### ERRORCALLBACK_INSTANCETYPE_STUDIO_COMMANDREPLAY *Type:* VARIABLE Errorcallback instancetype studio commandreplay. ### DSP_RESAMPLER_DEFAULT *Type:* VARIABLE DSP resampler - default. ### DSP_RESAMPLER_NOINTERP *Type:* VARIABLE DSP resampler - nointerp. ### DSP_RESAMPLER_LINEAR *Type:* VARIABLE DSP resampler - linear. ### DSP_RESAMPLER_CUBIC *Type:* VARIABLE DSP resampler - cubic. ### DSP_RESAMPLER_SPLINE *Type:* VARIABLE DSP resampler - spline. ### DSP_CALLBACK_DATAPARAMETERRELEASE *Type:* VARIABLE DSP callback type - dataparameterrelease. ### DSPCONNECTION_TYPE_STANDARD *Type:* VARIABLE DSP connection type - standard. ### DSPCONNECTION_TYPE_SIDECHAIN *Type:* VARIABLE DSP connection type - sidechain. ### DSPCONNECTION_TYPE_SEND *Type:* VARIABLE DSP connection type - send. ### DSPCONNECTION_TYPE_SEND_SIDECHAIN *Type:* VARIABLE DSP connection type - send sidechain. ### DSPCONNECTION_TYPE_PREALLOCATED *Type:* VARIABLE DSP connection type - preallocated. ### TAGTYPE_UNKNOWN *Type:* VARIABLE Tag type - unknown. ### TAGTYPE_ID3V1 *Type:* VARIABLE Tag type - id3v1. ### TAGTYPE_ID3V2 *Type:* VARIABLE Tag type - id3v2. ### TAGTYPE_VORBISCOMMENT *Type:* VARIABLE Tag type - vorbiscomment. ### TAGTYPE_SHOUTCAST *Type:* VARIABLE Tag type - shoutcast. ### TAGTYPE_ICECAST *Type:* VARIABLE Tag type - icecast. ### TAGTYPE_ASF *Type:* VARIABLE Tag type - asf. ### TAGTYPE_MIDI *Type:* VARIABLE Tag type - midi. ### TAGTYPE_PLAYLIST *Type:* VARIABLE Tag type - playlist. ### TAGTYPE_FMOD *Type:* VARIABLE Tag type - fmod. ### TAGTYPE_USER *Type:* VARIABLE Tag type - user. ### TAGDATATYPE_BINARY *Type:* VARIABLE Tag data type - binary. ### TAGDATATYPE_INT *Type:* VARIABLE Tag data type - int. ### TAGDATATYPE_FLOAT *Type:* VARIABLE Tag data type - float. ### TAGDATATYPE_STRING *Type:* VARIABLE Tag data type - string. ### TAGDATATYPE_STRING_UTF16 *Type:* VARIABLE Tag data type - string utf16. ### TAGDATATYPE_STRING_UTF16BE *Type:* VARIABLE Tag data type - string utf16be. ### TAGDATATYPE_STRING_UTF8 *Type:* VARIABLE Tag data type - string utf8. ### PORT_TYPE_MUSIC *Type:* VARIABLE Port type - music. ### PORT_TYPE_COPYRIGHT_MUSIC *Type:* VARIABLE Port type - copyright music. ### PORT_TYPE_VOICE *Type:* VARIABLE Port type - voice. ### PORT_TYPE_CONTROLLER *Type:* VARIABLE Port type - controller. ### PORT_TYPE_PERSONAL *Type:* VARIABLE Port type - personal. ### PORT_TYPE_VIBRATION *Type:* VARIABLE Port type - vibration. ### PORT_TYPE_AUX *Type:* VARIABLE Port type - aux. ### PORT_TYPE_PASSTHROUGH *Type:* VARIABLE Port type - passthrough. ### PORT_TYPE_VR_VIBRATION *Type:* VARIABLE Port type - vr vibration. ### DSP_TYPE_UNKNOWN *Type:* VARIABLE DSP effect type - unknown. ### DSP_TYPE_MIXER *Type:* VARIABLE DSP effect type - mixer. ### DSP_TYPE_OSCILLATOR *Type:* VARIABLE DSP effect type - oscillator. ### DSP_TYPE_LOWPASS *Type:* VARIABLE DSP effect type - lowpass. ### DSP_TYPE_ITLOWPASS *Type:* VARIABLE DSP effect type - itlowpass. ### DSP_TYPE_HIGHPASS *Type:* VARIABLE DSP effect type - highpass. ### DSP_TYPE_ECHO *Type:* VARIABLE DSP effect type - echo. ### DSP_TYPE_FADER *Type:* VARIABLE DSP effect type - fader. ### DSP_TYPE_FLANGE *Type:* VARIABLE DSP effect type - flange. ### DSP_TYPE_DISTORTION *Type:* VARIABLE DSP effect type - distortion. ### DSP_TYPE_NORMALIZE *Type:* VARIABLE DSP effect type - normalize. ### DSP_TYPE_LIMITER *Type:* VARIABLE DSP effect type - limiter. ### DSP_TYPE_PARAMEQ *Type:* VARIABLE DSP effect type - parameq. ### DSP_TYPE_PITCHSHIFT *Type:* VARIABLE DSP effect type - pitchshift. ### DSP_TYPE_CHORUS *Type:* VARIABLE DSP effect type - chorus. ### DSP_TYPE_ITECHO *Type:* VARIABLE DSP effect type - itecho. ### DSP_TYPE_COMPRESSOR *Type:* VARIABLE DSP effect type - compressor. ### DSP_TYPE_SFXREVERB *Type:* VARIABLE DSP effect type - sfxreverb. ### DSP_TYPE_LOWPASS_SIMPLE *Type:* VARIABLE DSP effect type - lowpass simple. ### DSP_TYPE_DELAY *Type:* VARIABLE DSP effect type - delay. ### DSP_TYPE_TREMOLO *Type:* VARIABLE DSP effect type - tremolo. ### DSP_TYPE_SEND *Type:* VARIABLE DSP effect type - send. ### DSP_TYPE_RETURN *Type:* VARIABLE DSP effect type - return. ### DSP_TYPE_HIGHPASS_SIMPLE *Type:* VARIABLE DSP effect type - highpass simple. ### DSP_TYPE_PAN *Type:* VARIABLE DSP effect type - pan. ### DSP_TYPE_THREE_EQ *Type:* VARIABLE DSP effect type - three eq. ### DSP_TYPE_FFT *Type:* VARIABLE DSP effect type - fft. ### DSP_TYPE_LOUDNESS_METER *Type:* VARIABLE DSP effect type - loudness meter. ### DSP_TYPE_CONVOLUTIONREVERB *Type:* VARIABLE DSP effect type - convolutionreverb. ### DSP_TYPE_CHANNELMIX *Type:* VARIABLE DSP effect type - channelmix. ### DSP_TYPE_TRANSCEIVER *Type:* VARIABLE DSP effect type - transceiver. ### DSP_TYPE_OBJECTPAN *Type:* VARIABLE DSP effect type - objectpan. ### DSP_TYPE_MULTIBAND_EQ *Type:* VARIABLE DSP effect type - multiband eq. ### DSP_TYPE_MULTIBAND_DYNAMICS *Type:* VARIABLE DSP effect type - multiband dynamics. ### DSP_OSCILLATOR_TYPE *Type:* VARIABLE Dsp oscillator type. ### DSP_OSCILLATOR_RATE *Type:* VARIABLE Dsp oscillator rate. ### DSP_LOWPASS_CUTOFF *Type:* VARIABLE Dsp lowpass cutoff. ### DSP_LOWPASS_RESONANCE *Type:* VARIABLE Dsp lowpass resonance. ### DSP_ITLOWPASS_CUTOFF *Type:* VARIABLE Dsp itlowpass cutoff. ### DSP_ITLOWPASS_RESONANCE *Type:* VARIABLE Dsp itlowpass resonance. ### DSP_HIGHPASS_CUTOFF *Type:* VARIABLE Dsp highpass cutoff. ### DSP_HIGHPASS_RESONANCE *Type:* VARIABLE Dsp highpass resonance. ### DSP_ECHO_DELAY *Type:* VARIABLE Dsp echo delay. ### DSP_ECHO_FEEDBACK *Type:* VARIABLE Dsp echo feedback. ### DSP_ECHO_DRYLEVEL *Type:* VARIABLE Dsp echo drylevel. ### DSP_ECHO_WETLEVEL *Type:* VARIABLE Dsp echo wetlevel. ### DSP_ECHO_DELAYCHANGEMODE *Type:* VARIABLE Dsp echo delaychangemode. ### DSP_ECHO_DELAYCHANGEMODE_FADE *Type:* VARIABLE Dsp echo delaychangemode fade. ### DSP_ECHO_DELAYCHANGEMODE_LERP *Type:* VARIABLE Dsp echo delaychangemode lerp. ### DSP_ECHO_DELAYCHANGEMODE_NONE *Type:* VARIABLE Dsp echo delaychangemode none. ### DSP_FADER_GAIN *Type:* VARIABLE Dsp fader gain. ### DSP_FADER_OVERALL_GAIN *Type:* VARIABLE Dsp fader overall gain. ### DSP_FLANGE_MIX *Type:* VARIABLE Dsp flange mix. ### DSP_FLANGE_DEPTH *Type:* VARIABLE Dsp flange depth. ### DSP_FLANGE_RATE *Type:* VARIABLE Dsp flange rate. ### DSP_DISTORTION_LEVEL *Type:* VARIABLE Dsp distortion level. ### DSP_NORMALIZE_FADETIME *Type:* VARIABLE Dsp normalize fadetime. ### DSP_NORMALIZE_THRESHOLD *Type:* VARIABLE Dsp normalize threshold. ### DSP_NORMALIZE_MAXAMP *Type:* VARIABLE Dsp normalize maxamp. ### DSP_LIMITER_RELEASETIME *Type:* VARIABLE Dsp limiter releasetime. ### DSP_LIMITER_CEILING *Type:* VARIABLE Dsp limiter ceiling. ### DSP_LIMITER_MAXIMIZERGAIN *Type:* VARIABLE Dsp limiter maximizergain. ### DSP_LIMITER_MODE *Type:* VARIABLE Dsp limiter mode. ### DSP_PARAMEQ_CENTER *Type:* VARIABLE Dsp parameq center. ### DSP_PARAMEQ_BANDWIDTH *Type:* VARIABLE Dsp parameq bandwidth. ### DSP_PARAMEQ_GAIN *Type:* VARIABLE Dsp parameq gain. ### DSP_MULTIBAND_EQ_A_FILTER *Type:* VARIABLE Dsp multiband eq a filter. ### DSP_MULTIBAND_EQ_A_FREQUENCY *Type:* VARIABLE Dsp multiband eq a frequency. ### DSP_MULTIBAND_EQ_A_Q *Type:* VARIABLE Dsp multiband eq a q. ### DSP_MULTIBAND_EQ_A_GAIN *Type:* VARIABLE Dsp multiband eq a gain. ### DSP_MULTIBAND_EQ_B_FILTER *Type:* VARIABLE Dsp multiband eq b filter. ### DSP_MULTIBAND_EQ_B_FREQUENCY *Type:* VARIABLE Dsp multiband eq b frequency. ### DSP_MULTIBAND_EQ_B_Q *Type:* VARIABLE Dsp multiband eq b q. ### DSP_MULTIBAND_EQ_B_GAIN *Type:* VARIABLE Dsp multiband eq b gain. ### DSP_MULTIBAND_EQ_C_FILTER *Type:* VARIABLE Dsp multiband eq c filter. ### DSP_MULTIBAND_EQ_C_FREQUENCY *Type:* VARIABLE Dsp multiband eq c frequency. ### DSP_MULTIBAND_EQ_C_Q *Type:* VARIABLE Dsp multiband eq c q. ### DSP_MULTIBAND_EQ_C_GAIN *Type:* VARIABLE Dsp multiband eq c gain. ### DSP_MULTIBAND_EQ_D_FILTER *Type:* VARIABLE Dsp multiband eq d filter. ### DSP_MULTIBAND_EQ_D_FREQUENCY *Type:* VARIABLE Dsp multiband eq d frequency. ### DSP_MULTIBAND_EQ_D_Q *Type:* VARIABLE Dsp multiband eq d q. ### DSP_MULTIBAND_EQ_D_GAIN *Type:* VARIABLE Dsp multiband eq d gain. ### DSP_MULTIBAND_EQ_E_FILTER *Type:* VARIABLE Dsp multiband eq e filter. ### DSP_MULTIBAND_EQ_E_FREQUENCY *Type:* VARIABLE Dsp multiband eq e frequency. ### DSP_MULTIBAND_EQ_E_Q *Type:* VARIABLE Dsp multiband eq e q. ### DSP_MULTIBAND_EQ_E_GAIN *Type:* VARIABLE Dsp multiband eq e gain. ### DSP_MULTIBAND_EQ_FILTER_DISABLED *Type:* VARIABLE Dsp multiband eq filter disabled. ### DSP_MULTIBAND_EQ_FILTER_LOWPASS_12DB *Type:* VARIABLE Dsp multiband eq filter lowpass 12db. ### DSP_MULTIBAND_EQ_FILTER_LOWPASS_24DB *Type:* VARIABLE Dsp multiband eq filter lowpass 24db. ### DSP_MULTIBAND_EQ_FILTER_LOWPASS_48DB *Type:* VARIABLE Dsp multiband eq filter lowpass 48db. ### DSP_MULTIBAND_EQ_FILTER_HIGHPASS_12DB *Type:* VARIABLE Dsp multiband eq filter highpass 12db. ### DSP_MULTIBAND_EQ_FILTER_HIGHPASS_24DB *Type:* VARIABLE Dsp multiband eq filter highpass 24db. ### DSP_MULTIBAND_EQ_FILTER_HIGHPASS_48DB *Type:* VARIABLE Dsp multiband eq filter highpass 48db. ### DSP_MULTIBAND_EQ_FILTER_LOWSHELF *Type:* VARIABLE Dsp multiband eq filter lowshelf. ### DSP_MULTIBAND_EQ_FILTER_HIGHSHELF *Type:* VARIABLE Dsp multiband eq filter highshelf. ### DSP_MULTIBAND_EQ_FILTER_PEAKING *Type:* VARIABLE Dsp multiband eq filter peaking. ### DSP_MULTIBAND_EQ_FILTER_BANDPASS *Type:* VARIABLE Dsp multiband eq filter bandpass. ### DSP_MULTIBAND_EQ_FILTER_NOTCH *Type:* VARIABLE Dsp multiband eq filter notch. ### DSP_MULTIBAND_EQ_FILTER_ALLPASS *Type:* VARIABLE Dsp multiband eq filter allpass. ### DSP_MULTIBAND_EQ_FILTER_LOWPASS_6DB *Type:* VARIABLE Dsp multiband eq filter lowpass 6db. ### DSP_MULTIBAND_EQ_FILTER_HIGHPASS_6DB *Type:* VARIABLE Dsp multiband eq filter highpass 6db. ### DSP_MULTIBAND_DYNAMICS_LOWER_FREQUENCY *Type:* VARIABLE Dsp multiband dynamics lower frequency. ### DSP_MULTIBAND_DYNAMICS_UPPER_FREQUENCY *Type:* VARIABLE Dsp multiband dynamics upper frequency. ### DSP_MULTIBAND_DYNAMICS_LINKED *Type:* VARIABLE Dsp multiband dynamics linked. ### DSP_MULTIBAND_DYNAMICS_USE_SIDECHAIN *Type:* VARIABLE Dsp multiband dynamics use sidechain. ### DSP_MULTIBAND_DYNAMICS_A_MODE *Type:* VARIABLE Dsp multiband dynamics a mode. ### DSP_MULTIBAND_DYNAMICS_A_GAIN *Type:* VARIABLE Dsp multiband dynamics a gain. ### DSP_MULTIBAND_DYNAMICS_A_THRESHOLD *Type:* VARIABLE Dsp multiband dynamics a threshold. ### DSP_MULTIBAND_DYNAMICS_A_RATIO *Type:* VARIABLE Dsp multiband dynamics a ratio. ### DSP_MULTIBAND_DYNAMICS_A_ATTACK *Type:* VARIABLE Dsp multiband dynamics a attack. ### DSP_MULTIBAND_DYNAMICS_A_RELEASE *Type:* VARIABLE Dsp multiband dynamics a release. ### DSP_MULTIBAND_DYNAMICS_A_GAIN_MAKEUP *Type:* VARIABLE Dsp multiband dynamics a gain makeup. ### DSP_MULTIBAND_DYNAMICS_A_RESPONSE_DATA *Type:* VARIABLE Dsp multiband dynamics a response data. ### DSP_MULTIBAND_DYNAMICS_B_MODE *Type:* VARIABLE Dsp multiband dynamics b mode. ### DSP_MULTIBAND_DYNAMICS_B_GAIN *Type:* VARIABLE Dsp multiband dynamics b gain. ### DSP_MULTIBAND_DYNAMICS_B_THRESHOLD *Type:* VARIABLE Dsp multiband dynamics b threshold. ### DSP_MULTIBAND_DYNAMICS_B_RATIO *Type:* VARIABLE Dsp multiband dynamics b ratio. ### DSP_MULTIBAND_DYNAMICS_B_ATTACK *Type:* VARIABLE Dsp multiband dynamics b attack. ### DSP_MULTIBAND_DYNAMICS_B_RELEASE *Type:* VARIABLE Dsp multiband dynamics b release. ### DSP_MULTIBAND_DYNAMICS_B_GAIN_MAKEUP *Type:* VARIABLE Dsp multiband dynamics b gain makeup. ### DSP_MULTIBAND_DYNAMICS_B_RESPONSE_DATA *Type:* VARIABLE Dsp multiband dynamics b response data. ### DSP_MULTIBAND_DYNAMICS_C_MODE *Type:* VARIABLE Dsp multiband dynamics c mode. ### DSP_MULTIBAND_DYNAMICS_C_GAIN *Type:* VARIABLE Dsp multiband dynamics c gain. ### DSP_MULTIBAND_DYNAMICS_C_THRESHOLD *Type:* VARIABLE Dsp multiband dynamics c threshold. ### DSP_MULTIBAND_DYNAMICS_C_RATIO *Type:* VARIABLE Dsp multiband dynamics c ratio. ### DSP_MULTIBAND_DYNAMICS_C_ATTACK *Type:* VARIABLE Dsp multiband dynamics c attack. ### DSP_MULTIBAND_DYNAMICS_C_RELEASE *Type:* VARIABLE Dsp multiband dynamics c release. ### DSP_MULTIBAND_DYNAMICS_C_GAIN_MAKEUP *Type:* VARIABLE Dsp multiband dynamics c gain makeup. ### DSP_MULTIBAND_DYNAMICS_C_RESPONSE_DATA *Type:* VARIABLE Dsp multiband dynamics c response data. ### DSP_MULTIBAND_DYNAMICS_MODE_DISABLED *Type:* VARIABLE Dsp multiband dynamics mode disabled. ### DSP_MULTIBAND_DYNAMICS_MODE_COMPRESS_UP *Type:* VARIABLE Dsp multiband dynamics mode compress up. ### DSP_MULTIBAND_DYNAMICS_MODE_COMPRESS_DOWN *Type:* VARIABLE Dsp multiband dynamics mode compress down. ### DSP_MULTIBAND_DYNAMICS_MODE_EXPAND_UP *Type:* VARIABLE Dsp multiband dynamics mode expand up. ### DSP_MULTIBAND_DYNAMICS_MODE_EXPAND_DOWN *Type:* VARIABLE Dsp multiband dynamics mode expand down. ### DSP_PITCHSHIFT_PITCH *Type:* VARIABLE Dsp pitchshift pitch. ### DSP_PITCHSHIFT_FFTSIZE *Type:* VARIABLE Dsp pitchshift fftsize. ### DSP_PITCHSHIFT_OVERLAP *Type:* VARIABLE Dsp pitchshift overlap. ### DSP_PITCHSHIFT_MAXCHANNELS *Type:* VARIABLE Dsp pitchshift maxchannels. ### DSP_CHORUS_MIX *Type:* VARIABLE Dsp chorus mix. ### DSP_CHORUS_RATE *Type:* VARIABLE Dsp chorus rate. ### DSP_CHORUS_DEPTH *Type:* VARIABLE Dsp chorus depth. ### DSP_ITECHO_WETDRYMIX *Type:* VARIABLE Dsp itecho wetdrymix. ### DSP_ITECHO_FEEDBACK *Type:* VARIABLE Dsp itecho feedback. ### DSP_ITECHO_LEFTDELAY *Type:* VARIABLE Dsp itecho leftdelay. ### DSP_ITECHO_RIGHTDELAY *Type:* VARIABLE Dsp itecho rightdelay. ### DSP_ITECHO_PANDELAY *Type:* VARIABLE Dsp itecho pandelay. ### DSP_COMPRESSOR_THRESHOLD *Type:* VARIABLE Dsp compressor threshold. ### DSP_COMPRESSOR_RATIO *Type:* VARIABLE Dsp compressor ratio. ### DSP_COMPRESSOR_ATTACK *Type:* VARIABLE Dsp compressor attack. ### DSP_COMPRESSOR_RELEASE *Type:* VARIABLE Dsp compressor release. ### DSP_COMPRESSOR_GAINMAKEUP *Type:* VARIABLE Dsp compressor gainmakeup. ### DSP_COMPRESSOR_USESIDECHAIN *Type:* VARIABLE Dsp compressor usesidechain. ### DSP_COMPRESSOR_LINKED *Type:* VARIABLE Dsp compressor linked. ### DSP_SFXREVERB_DECAYTIME *Type:* VARIABLE Dsp sfxreverb decaytime. ### DSP_SFXREVERB_EARLYDELAY *Type:* VARIABLE Dsp sfxreverb earlydelay. ### DSP_SFXREVERB_LATEDELAY *Type:* VARIABLE Dsp sfxreverb latedelay. ### DSP_SFXREVERB_HFREFERENCE *Type:* VARIABLE Dsp sfxreverb hfreference. ### DSP_SFXREVERB_HFDECAYRATIO *Type:* VARIABLE Dsp sfxreverb hfdecayratio. ### DSP_SFXREVERB_DIFFUSION *Type:* VARIABLE Dsp sfxreverb diffusion. ### DSP_SFXREVERB_DENSITY *Type:* VARIABLE Dsp sfxreverb density. ### DSP_SFXREVERB_LOWSHELFFREQUENCY *Type:* VARIABLE Dsp sfxreverb lowshelffrequency. ### DSP_SFXREVERB_LOWSHELFGAIN *Type:* VARIABLE Dsp sfxreverb lowshelfgain. ### DSP_SFXREVERB_HIGHCUT *Type:* VARIABLE Dsp sfxreverb highcut. ### DSP_SFXREVERB_EARLYLATEMIX *Type:* VARIABLE Dsp sfxreverb earlylatemix. ### DSP_SFXREVERB_WETLEVEL *Type:* VARIABLE Dsp sfxreverb wetlevel. ### DSP_SFXREVERB_DRYLEVEL *Type:* VARIABLE Dsp sfxreverb drylevel. ### DSP_LOWPASS_SIMPLE_CUTOFF *Type:* VARIABLE Dsp lowpass simple cutoff. ### DSP_DELAY_CH0 *Type:* VARIABLE Dsp delay ch0. ### DSP_DELAY_CH1 *Type:* VARIABLE Dsp delay ch1. ### DSP_DELAY_CH2 *Type:* VARIABLE Dsp delay ch2. ### DSP_DELAY_CH3 *Type:* VARIABLE Dsp delay ch3. ### DSP_DELAY_CH4 *Type:* VARIABLE Dsp delay ch4. ### DSP_DELAY_CH5 *Type:* VARIABLE Dsp delay ch5. ### DSP_DELAY_CH6 *Type:* VARIABLE Dsp delay ch6. ### DSP_DELAY_CH7 *Type:* VARIABLE Dsp delay ch7. ### DSP_DELAY_CH8 *Type:* VARIABLE Dsp delay ch8. ### DSP_DELAY_CH9 *Type:* VARIABLE Dsp delay ch9. ### DSP_DELAY_CH10 *Type:* VARIABLE Dsp delay ch10. ### DSP_DELAY_CH11 *Type:* VARIABLE Dsp delay ch11. ### DSP_DELAY_CH12 *Type:* VARIABLE Dsp delay ch12. ### DSP_DELAY_CH13 *Type:* VARIABLE Dsp delay ch13. ### DSP_DELAY_CH14 *Type:* VARIABLE Dsp delay ch14. ### DSP_DELAY_CH15 *Type:* VARIABLE Dsp delay ch15. ### DSP_DELAY_MAXDELAY *Type:* VARIABLE Dsp delay maxdelay. ### DSP_TREMOLO_FREQUENCY *Type:* VARIABLE Dsp tremolo frequency. ### DSP_TREMOLO_DEPTH *Type:* VARIABLE Dsp tremolo depth. ### DSP_TREMOLO_SHAPE *Type:* VARIABLE Dsp tremolo shape. ### DSP_TREMOLO_SKEW *Type:* VARIABLE Dsp tremolo skew. ### DSP_TREMOLO_DUTY *Type:* VARIABLE Dsp tremolo duty. ### DSP_TREMOLO_SQUARE *Type:* VARIABLE Dsp tremolo square. ### DSP_TREMOLO_PHASE *Type:* VARIABLE Dsp tremolo phase. ### DSP_TREMOLO_SPREAD *Type:* VARIABLE Dsp tremolo spread. ### DSP_SEND_RETURNID *Type:* VARIABLE Dsp send returnid. ### DSP_SEND_LEVEL *Type:* VARIABLE Dsp send level. ### DSP_RETURN_ID *Type:* VARIABLE Dsp return id. ### DSP_RETURN_INPUT_SPEAKER_MODE *Type:* VARIABLE Dsp return input speaker mode. ### DSP_HIGHPASS_SIMPLE_CUTOFF *Type:* VARIABLE Dsp highpass simple cutoff. ### DSP_PAN_2D_STEREO_MODE_DISTRIBUTED *Type:* VARIABLE Dsp pan 2d stereo mode distributed. ### DSP_PAN_2D_STEREO_MODE_DISCRETE *Type:* VARIABLE Dsp pan 2d stereo mode discrete. ### DSP_PAN_MODE_MONO *Type:* VARIABLE Dsp pan mode mono. ### DSP_PAN_MODE_STEREO *Type:* VARIABLE Dsp pan mode stereo. ### DSP_PAN_MODE_SURROUND *Type:* VARIABLE Dsp pan mode surround. ### DSP_PAN_3D_ROLLOFF_LINEARSQUARED *Type:* VARIABLE Pan 3D rolloff type - linearsquared. ### DSP_PAN_3D_ROLLOFF_LINEAR *Type:* VARIABLE Pan 3D rolloff type - linear. ### DSP_PAN_3D_ROLLOFF_INVERSE *Type:* VARIABLE Pan 3D rolloff type - inverse. ### DSP_PAN_3D_ROLLOFF_INVERSETAPERED *Type:* VARIABLE Pan 3D rolloff type - inversetapered. ### DSP_PAN_3D_ROLLOFF_CUSTOM *Type:* VARIABLE Pan 3D rolloff type - custom. ### DSP_PAN_3D_EXTENT_MODE_AUTO *Type:* VARIABLE Dsp pan 3d extent mode auto. ### DSP_PAN_3D_EXTENT_MODE_USER *Type:* VARIABLE Dsp pan 3d extent mode user. ### DSP_PAN_3D_EXTENT_MODE_OFF *Type:* VARIABLE Dsp pan 3d extent mode off. ### DSP_PAN_MODE *Type:* VARIABLE Dsp pan mode. ### DSP_PAN_2D_STEREO_POSITION *Type:* VARIABLE Dsp pan 2d stereo position. ### DSP_PAN_2D_DIRECTION *Type:* VARIABLE Dsp pan 2d direction. ### DSP_PAN_2D_EXTENT *Type:* VARIABLE Dsp pan 2d extent. ### DSP_PAN_2D_ROTATION *Type:* VARIABLE Dsp pan 2d rotation. ### DSP_PAN_2D_LFE_LEVEL *Type:* VARIABLE Dsp pan 2d lfe level. ### DSP_PAN_2D_STEREO_MODE *Type:* VARIABLE Dsp pan 2d stereo mode. ### DSP_PAN_2D_STEREO_SEPARATION *Type:* VARIABLE Dsp pan 2d stereo separation. ### DSP_PAN_2D_STEREO_AXIS *Type:* VARIABLE Dsp pan 2d stereo axis. ### DSP_PAN_ENABLED_SPEAKERS *Type:* VARIABLE Dsp pan enabled speakers. ### DSP_PAN_3D_POSITION *Type:* VARIABLE Dsp pan 3d position. ### DSP_PAN_3D_ROLLOFF *Type:* VARIABLE Dsp pan 3d rolloff. ### DSP_PAN_3D_MIN_DISTANCE *Type:* VARIABLE Dsp pan 3d min distance. ### DSP_PAN_3D_MAX_DISTANCE *Type:* VARIABLE Dsp pan 3d max distance. ### DSP_PAN_3D_EXTENT_MODE *Type:* VARIABLE Dsp pan 3d extent mode. ### DSP_PAN_3D_SOUND_SIZE *Type:* VARIABLE Dsp pan 3d sound size. ### DSP_PAN_3D_MIN_EXTENT *Type:* VARIABLE Dsp pan 3d min extent. ### DSP_PAN_3D_PAN_BLEND *Type:* VARIABLE Dsp pan 3d pan blend. ### DSP_PAN_LFE_UPMIX_ENABLED *Type:* VARIABLE Dsp pan lfe upmix enabled. ### DSP_PAN_OVERALL_GAIN *Type:* VARIABLE Dsp pan overall gain. ### DSP_PAN_SURROUND_SPEAKER_MODE *Type:* VARIABLE Pan surround mode - speaker mode. ### DSP_PAN_2D_HEIGHT_BLEND *Type:* VARIABLE Dsp pan 2d height blend. ### DSP_PAN_ATTENUATION_RANGE *Type:* VARIABLE Dsp pan attenuation range. ### DSP_PAN_OVERRIDE_RANGE *Type:* VARIABLE Dsp pan override range. ### DSP_THREE_EQ_CROSSOVERSLOPE_12DB *Type:* VARIABLE Dsp three eq crossoverslope 12db. ### DSP_THREE_EQ_CROSSOVERSLOPE_24DB *Type:* VARIABLE Dsp three eq crossoverslope 24db. ### DSP_THREE_EQ_CROSSOVERSLOPE_48DB *Type:* VARIABLE Dsp three eq crossoverslope 48db. ### DSP_THREE_EQ_LOWGAIN *Type:* VARIABLE Dsp three eq lowgain. ### DSP_THREE_EQ_MIDGAIN *Type:* VARIABLE Dsp three eq midgain. ### DSP_THREE_EQ_HIGHGAIN *Type:* VARIABLE Dsp three eq highgain. ### DSP_THREE_EQ_LOWCROSSOVER *Type:* VARIABLE Dsp three eq lowcrossover. ### DSP_THREE_EQ_HIGHCROSSOVER *Type:* VARIABLE Dsp three eq highcrossover. ### DSP_THREE_EQ_CROSSOVERSLOPE *Type:* VARIABLE Dsp three eq crossoverslope. ### DSP_FFT_WINDOW_RECT *Type:* VARIABLE Dsp fft window rect. ### DSP_FFT_WINDOW_TRIANGLE *Type:* VARIABLE Dsp fft window triangle. ### DSP_FFT_WINDOW_HAMMING *Type:* VARIABLE Dsp fft window hamming. ### DSP_FFT_WINDOW_HANNING *Type:* VARIABLE Dsp fft window hanning. ### DSP_FFT_WINDOW_BLACKMAN *Type:* VARIABLE Dsp fft window blackman. ### DSP_FFT_WINDOW_BLACKMANHARRIS *Type:* VARIABLE Dsp fft window blackmanharris. ### DSP_FFT_DOWNMIX_NONE *Type:* VARIABLE Dsp fft downmix none. ### DSP_FFT_DOWNMIX_MONO *Type:* VARIABLE Dsp fft downmix mono. ### DSP_FFT_WINDOWSIZE *Type:* VARIABLE Dsp fft windowsize. ### DSP_FFT_WINDOW *Type:* VARIABLE Dsp fft window. ### DSP_FFT_BAND_START_FREQ *Type:* VARIABLE Dsp fft band start freq. ### DSP_FFT_BAND_STOP_FREQ *Type:* VARIABLE Dsp fft band stop freq. ### DSP_FFT_SPECTRUMDATA *Type:* VARIABLE Dsp fft spectrumdata. ### DSP_FFT_RMS *Type:* VARIABLE Dsp fft rms. ### DSP_FFT_SPECTRAL_CENTROID *Type:* VARIABLE Dsp fft spectral centroid. ### DSP_FFT_IMMEDIATE_MODE *Type:* VARIABLE Dsp fft immediate mode. ### DSP_FFT_DOWNMIX *Type:* VARIABLE Dsp fft downmix. ### DSP_FFT_CHANNEL *Type:* VARIABLE Dsp fft channel. ### DSP_LOUDNESS_METER_STATE *Type:* VARIABLE Dsp loudness meter state. ### DSP_LOUDNESS_METER_WEIGHTING *Type:* VARIABLE Dsp loudness meter weighting. ### DSP_LOUDNESS_METER_INFO *Type:* VARIABLE Dsp loudness meter info. ### DSP_LOUDNESS_METER_STATE_RESET_INTEGRATED *Type:* VARIABLE Dsp loudness meter state reset integrated. ### DSP_LOUDNESS_METER_STATE_RESET_MAXPEAK *Type:* VARIABLE Dsp loudness meter state reset maxpeak. ### DSP_LOUDNESS_METER_STATE_RESET_ALL *Type:* VARIABLE Dsp loudness meter state reset all. ### DSP_LOUDNESS_METER_STATE_PAUSED *Type:* VARIABLE Dsp loudness meter state paused. ### DSP_LOUDNESS_METER_STATE_ANALYZING *Type:* VARIABLE Dsp loudness meter state analyzing. ### DSP_CONVOLUTION_REVERB_PARAM_IR *Type:* VARIABLE Dsp convolution reverb param ir. ### DSP_CONVOLUTION_REVERB_PARAM_WET *Type:* VARIABLE Dsp convolution reverb param wet. ### DSP_CONVOLUTION_REVERB_PARAM_DRY *Type:* VARIABLE Dsp convolution reverb param dry. ### DSP_CONVOLUTION_REVERB_PARAM_LINKED *Type:* VARIABLE Dsp convolution reverb param linked. ### DSP_CHANNELMIX_OUTPUT_DEFAULT *Type:* VARIABLE Dsp channelmix output default. ### DSP_CHANNELMIX_OUTPUT_ALLMONO *Type:* VARIABLE Dsp channelmix output allmono. ### DSP_CHANNELMIX_OUTPUT_ALLSTEREO *Type:* VARIABLE Dsp channelmix output allstereo. ### DSP_CHANNELMIX_OUTPUT_ALLQUAD *Type:* VARIABLE Dsp channelmix output allquad. ### DSP_CHANNELMIX_OUTPUT_ALL5POINT1 *Type:* VARIABLE Dsp channelmix output all5point1. ### DSP_CHANNELMIX_OUTPUT_ALL7POINT1 *Type:* VARIABLE Dsp channelmix output all7point1. ### DSP_CHANNELMIX_OUTPUT_ALLLFE *Type:* VARIABLE Dsp channelmix output alllfe. ### DSP_CHANNELMIX_OUTPUT_ALL7POINT1POINT4 *Type:* VARIABLE Dsp channelmix output all7point1point4. ### DSP_CHANNELMIX_OUTPUTGROUPING *Type:* VARIABLE Dsp channelmix outputgrouping. ### DSP_CHANNELMIX_GAIN_CH0 *Type:* VARIABLE Dsp channelmix gain ch0. ### DSP_CHANNELMIX_GAIN_CH1 *Type:* VARIABLE Dsp channelmix gain ch1. ### DSP_CHANNELMIX_GAIN_CH2 *Type:* VARIABLE Dsp channelmix gain ch2. ### DSP_CHANNELMIX_GAIN_CH3 *Type:* VARIABLE Dsp channelmix gain ch3. ### DSP_CHANNELMIX_GAIN_CH4 *Type:* VARIABLE Dsp channelmix gain ch4. ### DSP_CHANNELMIX_GAIN_CH5 *Type:* VARIABLE Dsp channelmix gain ch5. ### DSP_CHANNELMIX_GAIN_CH6 *Type:* VARIABLE Dsp channelmix gain ch6. ### DSP_CHANNELMIX_GAIN_CH7 *Type:* VARIABLE Dsp channelmix gain ch7. ### DSP_CHANNELMIX_GAIN_CH8 *Type:* VARIABLE Dsp channelmix gain ch8. ### DSP_CHANNELMIX_GAIN_CH9 *Type:* VARIABLE Dsp channelmix gain ch9. ### DSP_CHANNELMIX_GAIN_CH10 *Type:* VARIABLE Dsp channelmix gain ch10. ### DSP_CHANNELMIX_GAIN_CH11 *Type:* VARIABLE Dsp channelmix gain ch11. ### DSP_CHANNELMIX_GAIN_CH12 *Type:* VARIABLE Dsp channelmix gain ch12. ### DSP_CHANNELMIX_GAIN_CH13 *Type:* VARIABLE Dsp channelmix gain ch13. ### DSP_CHANNELMIX_GAIN_CH14 *Type:* VARIABLE Dsp channelmix gain ch14. ### DSP_CHANNELMIX_GAIN_CH15 *Type:* VARIABLE Dsp channelmix gain ch15. ### DSP_CHANNELMIX_GAIN_CH16 *Type:* VARIABLE Dsp channelmix gain ch16. ### DSP_CHANNELMIX_GAIN_CH17 *Type:* VARIABLE Dsp channelmix gain ch17. ### DSP_CHANNELMIX_GAIN_CH18 *Type:* VARIABLE Dsp channelmix gain ch18. ### DSP_CHANNELMIX_GAIN_CH19 *Type:* VARIABLE Dsp channelmix gain ch19. ### DSP_CHANNELMIX_GAIN_CH20 *Type:* VARIABLE Dsp channelmix gain ch20. ### DSP_CHANNELMIX_GAIN_CH21 *Type:* VARIABLE Dsp channelmix gain ch21. ### DSP_CHANNELMIX_GAIN_CH22 *Type:* VARIABLE Dsp channelmix gain ch22. ### DSP_CHANNELMIX_GAIN_CH23 *Type:* VARIABLE Dsp channelmix gain ch23. ### DSP_CHANNELMIX_GAIN_CH24 *Type:* VARIABLE Dsp channelmix gain ch24. ### DSP_CHANNELMIX_GAIN_CH25 *Type:* VARIABLE Dsp channelmix gain ch25. ### DSP_CHANNELMIX_GAIN_CH26 *Type:* VARIABLE Dsp channelmix gain ch26. ### DSP_CHANNELMIX_GAIN_CH27 *Type:* VARIABLE Dsp channelmix gain ch27. ### DSP_CHANNELMIX_GAIN_CH28 *Type:* VARIABLE Dsp channelmix gain ch28. ### DSP_CHANNELMIX_GAIN_CH29 *Type:* VARIABLE Dsp channelmix gain ch29. ### DSP_CHANNELMIX_GAIN_CH30 *Type:* VARIABLE Dsp channelmix gain ch30. ### DSP_CHANNELMIX_GAIN_CH31 *Type:* VARIABLE Dsp channelmix gain ch31. ### DSP_CHANNELMIX_OUTPUT_CH0 *Type:* VARIABLE Dsp channelmix output ch0. ### DSP_CHANNELMIX_OUTPUT_CH1 *Type:* VARIABLE Dsp channelmix output ch1. ### DSP_CHANNELMIX_OUTPUT_CH2 *Type:* VARIABLE Dsp channelmix output ch2. ### DSP_CHANNELMIX_OUTPUT_CH3 *Type:* VARIABLE Dsp channelmix output ch3. ### DSP_CHANNELMIX_OUTPUT_CH4 *Type:* VARIABLE Dsp channelmix output ch4. ### DSP_CHANNELMIX_OUTPUT_CH5 *Type:* VARIABLE Dsp channelmix output ch5. ### DSP_CHANNELMIX_OUTPUT_CH6 *Type:* VARIABLE Dsp channelmix output ch6. ### DSP_CHANNELMIX_OUTPUT_CH7 *Type:* VARIABLE Dsp channelmix output ch7. ### DSP_CHANNELMIX_OUTPUT_CH8 *Type:* VARIABLE Dsp channelmix output ch8. ### DSP_CHANNELMIX_OUTPUT_CH9 *Type:* VARIABLE Dsp channelmix output ch9. ### DSP_CHANNELMIX_OUTPUT_CH10 *Type:* VARIABLE Dsp channelmix output ch10. ### DSP_CHANNELMIX_OUTPUT_CH11 *Type:* VARIABLE Dsp channelmix output ch11. ### DSP_CHANNELMIX_OUTPUT_CH12 *Type:* VARIABLE Dsp channelmix output ch12. ### DSP_CHANNELMIX_OUTPUT_CH13 *Type:* VARIABLE Dsp channelmix output ch13. ### DSP_CHANNELMIX_OUTPUT_CH14 *Type:* VARIABLE Dsp channelmix output ch14. ### DSP_CHANNELMIX_OUTPUT_CH15 *Type:* VARIABLE Dsp channelmix output ch15. ### DSP_CHANNELMIX_OUTPUT_CH16 *Type:* VARIABLE Dsp channelmix output ch16. ### DSP_CHANNELMIX_OUTPUT_CH17 *Type:* VARIABLE Dsp channelmix output ch17. ### DSP_CHANNELMIX_OUTPUT_CH18 *Type:* VARIABLE Dsp channelmix output ch18. ### DSP_CHANNELMIX_OUTPUT_CH19 *Type:* VARIABLE Dsp channelmix output ch19. ### DSP_CHANNELMIX_OUTPUT_CH20 *Type:* VARIABLE Dsp channelmix output ch20. ### DSP_CHANNELMIX_OUTPUT_CH21 *Type:* VARIABLE Dsp channelmix output ch21. ### DSP_CHANNELMIX_OUTPUT_CH22 *Type:* VARIABLE Dsp channelmix output ch22. ### DSP_CHANNELMIX_OUTPUT_CH23 *Type:* VARIABLE Dsp channelmix output ch23. ### DSP_CHANNELMIX_OUTPUT_CH24 *Type:* VARIABLE Dsp channelmix output ch24. ### DSP_CHANNELMIX_OUTPUT_CH25 *Type:* VARIABLE Dsp channelmix output ch25. ### DSP_CHANNELMIX_OUTPUT_CH26 *Type:* VARIABLE Dsp channelmix output ch26. ### DSP_CHANNELMIX_OUTPUT_CH27 *Type:* VARIABLE Dsp channelmix output ch27. ### DSP_CHANNELMIX_OUTPUT_CH28 *Type:* VARIABLE Dsp channelmix output ch28. ### DSP_CHANNELMIX_OUTPUT_CH29 *Type:* VARIABLE Dsp channelmix output ch29. ### DSP_CHANNELMIX_OUTPUT_CH30 *Type:* VARIABLE Dsp channelmix output ch30. ### DSP_CHANNELMIX_OUTPUT_CH31 *Type:* VARIABLE Dsp channelmix output ch31. ### DSP_TRANSCEIVER_SPEAKERMODE_AUTO *Type:* VARIABLE Dsp transceiver speakermode auto. ### DSP_TRANSCEIVER_SPEAKERMODE_MONO *Type:* VARIABLE Dsp transceiver speakermode mono. ### DSP_TRANSCEIVER_SPEAKERMODE_STEREO *Type:* VARIABLE Dsp transceiver speakermode stereo. ### DSP_TRANSCEIVER_SPEAKERMODE_SURROUND *Type:* VARIABLE Dsp transceiver speakermode surround. ### DSP_TRANSCEIVER_TRANSMIT *Type:* VARIABLE Dsp transceiver transmit. ### DSP_TRANSCEIVER_GAIN *Type:* VARIABLE Dsp transceiver gain. ### DSP_TRANSCEIVER_CHANNEL *Type:* VARIABLE Dsp transceiver channel. ### DSP_TRANSCEIVER_TRANSMITSPEAKERMODE *Type:* VARIABLE Dsp transceiver transmitspeakermode. ### DSP_OBJECTPAN_3D_POSITION *Type:* VARIABLE Dsp objectpan 3d position. ### DSP_OBJECTPAN_3D_ROLLOFF *Type:* VARIABLE Dsp objectpan 3d rolloff. ### DSP_OBJECTPAN_3D_MIN_DISTANCE *Type:* VARIABLE Dsp objectpan 3d min distance. ### DSP_OBJECTPAN_3D_MAX_DISTANCE *Type:* VARIABLE Dsp objectpan 3d max distance. ### DSP_OBJECTPAN_3D_EXTENT_MODE *Type:* VARIABLE Dsp objectpan 3d extent mode. ### DSP_OBJECTPAN_3D_SOUND_SIZE *Type:* VARIABLE Dsp objectpan 3d sound size. ### DSP_OBJECTPAN_3D_MIN_EXTENT *Type:* VARIABLE Dsp objectpan 3d min extent. ### DSP_OBJECTPAN_OVERALL_GAIN *Type:* VARIABLE Dsp objectpan overall gain. ### DSP_OBJECTPAN_OUTPUTGAIN *Type:* VARIABLE Dsp objectpan outputgain. ### DSP_OBJECTPAN_ATTENUATION_RANGE *Type:* VARIABLE Dsp objectpan attenuation range. ### DSP_OBJECTPAN_OVERRIDE_RANGE *Type:* VARIABLE Dsp objectpan override range. ### DSP_PROCESS_PERFORM *Type:* VARIABLE Dsp process perform. ### DSP_PROCESS_QUERY *Type:* VARIABLE Dsp process query. ### DSP_PAN_SURROUND_DEFAULT *Type:* VARIABLE Pan surround mode - default. ### DSP_PAN_SURROUND_ROTATION_NOT_BIASED *Type:* VARIABLE Pan surround mode - rotation not biased. ### DSP_PARAMETER_TYPE_FLOAT *Type:* VARIABLE DSP parameter type - float. ### DSP_PARAMETER_TYPE_INT *Type:* VARIABLE DSP parameter type - int. ### DSP_PARAMETER_TYPE_BOOL *Type:* VARIABLE DSP parameter type - bool. ### DSP_PARAMETER_TYPE_DATA *Type:* VARIABLE DSP parameter type - data. ### DSP_PARAMETER_FLOAT_MAPPING_TYPE_LINEAR *Type:* VARIABLE Dsp parameter float mapping type linear. ### DSP_PARAMETER_FLOAT_MAPPING_TYPE_AUTO *Type:* VARIABLE Dsp parameter float mapping type auto. ### DSP_PARAMETER_FLOAT_MAPPING_TYPE_PIECEWISE_LINEAR *Type:* VARIABLE Dsp parameter float mapping type piecewise linear. ### DSP_PARAMETER_DATA_TYPE_USER *Type:* VARIABLE Dsp parameter data type user. ### DSP_PARAMETER_DATA_TYPE_OVERALLGAIN *Type:* VARIABLE Dsp parameter data type overallgain. ### DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES *Type:* VARIABLE Dsp parameter data type 3dattributes. ### DSP_PARAMETER_DATA_TYPE_SIDECHAIN *Type:* VARIABLE Dsp parameter data type sidechain. ### DSP_PARAMETER_DATA_TYPE_FFT *Type:* VARIABLE Dsp parameter data type fft. ### DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES_MULTI *Type:* VARIABLE Dsp parameter data type 3dattributes multi. ### DSP_PARAMETER_DATA_TYPE_ATTENUATION_RANGE *Type:* VARIABLE Dsp parameter data type attenuation range. ### DSP_PARAMETER_DATA_TYPE_DYNAMIC_RESPONSE *Type:* VARIABLE Dsp parameter data type dynamic response. ### STUDIO_LOADING_STATE_UNLOADING *Type:* VARIABLE Loading state - unloading. ### STUDIO_LOADING_STATE_UNLOADED *Type:* VARIABLE Loading state - unloaded. ### STUDIO_LOADING_STATE_LOADING *Type:* VARIABLE Loading state - loading. ### STUDIO_LOADING_STATE_LOADED *Type:* VARIABLE Loading state - loaded. ### STUDIO_LOADING_STATE_ERROR *Type:* VARIABLE Loading state - error. ### STUDIO_LOAD_MEMORY *Type:* VARIABLE Studio load memory. ### STUDIO_LOAD_MEMORY_POINT *Type:* VARIABLE Studio load memory point. ### STUDIO_PARAMETER_GAME_CONTROLLED *Type:* VARIABLE Studio parameter type - game controlled. ### STUDIO_PARAMETER_AUTOMATIC_DISTANCE *Type:* VARIABLE Studio parameter type - automatic distance. ### STUDIO_PARAMETER_AUTOMATIC_EVENT_CONE_ANGLE *Type:* VARIABLE Studio parameter type - automatic event cone angle. ### STUDIO_PARAMETER_AUTOMATIC_EVENT_ORIENTATION *Type:* VARIABLE Studio parameter type - automatic event orientation. ### STUDIO_PARAMETER_AUTOMATIC_DIRECTION *Type:* VARIABLE Studio parameter type - automatic direction. ### STUDIO_PARAMETER_AUTOMATIC_ELEVATION *Type:* VARIABLE Studio parameter type - automatic elevation. ### STUDIO_PARAMETER_AUTOMATIC_LISTENER_ORIENTATION *Type:* VARIABLE Studio parameter type - automatic listener orientation. ### STUDIO_PARAMETER_AUTOMATIC_SPEED *Type:* VARIABLE Studio parameter type - automatic speed. ### STUDIO_PARAMETER_AUTOMATIC_SPEED_ABSOLUTE *Type:* VARIABLE Studio parameter type - automatic speed absolute. ### STUDIO_PARAMETER_AUTOMATIC_DISTANCE_NORMALIZED *Type:* VARIABLE Studio parameter type - automatic distance normalized. ### STUDIO_USER_PROPERTY_TYPE_INTEGER *Type:* VARIABLE User property type - integer. ### STUDIO_USER_PROPERTY_TYPE_BOOLEAN *Type:* VARIABLE User property type - boolean. ### STUDIO_USER_PROPERTY_TYPE_FLOAT *Type:* VARIABLE User property type - float. ### STUDIO_USER_PROPERTY_TYPE_STRING *Type:* VARIABLE User property type - string. ### STUDIO_EVENT_PROPERTY_CHANNELPRIORITY *Type:* VARIABLE Event property - channelpriority. ### STUDIO_EVENT_PROPERTY_SCHEDULE_DELAY *Type:* VARIABLE Event property - schedule delay. ### STUDIO_EVENT_PROPERTY_SCHEDULE_LOOKAHEAD *Type:* VARIABLE Event property - schedule lookahead. ### STUDIO_EVENT_PROPERTY_MINIMUM_DISTANCE *Type:* VARIABLE Event property - minimum distance. ### STUDIO_EVENT_PROPERTY_MAXIMUM_DISTANCE *Type:* VARIABLE Event property - maximum distance. ### STUDIO_EVENT_PROPERTY_COOLDOWN *Type:* VARIABLE Event property - cooldown. ### STUDIO_PLAYBACK_PLAYING *Type:* VARIABLE Playback state - playing. ### STUDIO_PLAYBACK_SUSTAINING *Type:* VARIABLE Playback state - sustaining. ### STUDIO_PLAYBACK_STOPPED *Type:* VARIABLE Playback state - stopped. ### STUDIO_PLAYBACK_STARTING *Type:* VARIABLE Playback state - starting. ### STUDIO_PLAYBACK_STOPPING *Type:* VARIABLE Playback state - stopping. ### STUDIO_STOP_ALLOWFADEOUT *Type:* VARIABLE Stop mode - allowfadeout. ### STUDIO_STOP_IMMEDIATE *Type:* VARIABLE Stop mode - immediate. ### STUDIO_INSTANCETYPE_NONE *Type:* VARIABLE Instance type - none. ### STUDIO_INSTANCETYPE_SYSTEM *Type:* VARIABLE Instance type - system. ### STUDIO_INSTANCETYPE_EVENTDESCRIPTION *Type:* VARIABLE Instance type - eventdescription. ### STUDIO_INSTANCETYPE_EVENTINSTANCE *Type:* VARIABLE Instance type - eventinstance. ### STUDIO_INSTANCETYPE_PARAMETERINSTANCE *Type:* VARIABLE Instance type - parameterinstance. ### STUDIO_INSTANCETYPE_BUS *Type:* VARIABLE Instance type - bus. ### STUDIO_INSTANCETYPE_VCA *Type:* VARIABLE Instance type - vca. ### STUDIO_INSTANCETYPE_BANK *Type:* VARIABLE Instance type - bank. ### STUDIO_INSTANCETYPE_COMMANDREPLAY *Type:* VARIABLE Instance type - commandreplay. ### VERSION *Type:* VARIABLE Version. ### BUILDNUMBER *Type:* VARIABLE Buildnumber. ### DEBUG_LEVEL_NONE *Type:* VARIABLE Debug level none. ### DEBUG_LEVEL_ERROR *Type:* VARIABLE Debug level error. ### DEBUG_LEVEL_WARNING *Type:* VARIABLE Debug level warning. ### DEBUG_LEVEL_LOG *Type:* VARIABLE Debug level log. ### DEBUG_TYPE_MEMORY *Type:* VARIABLE Debug type memory. ### DEBUG_TYPE_FILE *Type:* VARIABLE Debug type file. ### DEBUG_TYPE_CODEC *Type:* VARIABLE Debug type codec. ### DEBUG_TYPE_TRACE *Type:* VARIABLE Debug type trace. ### DEBUG_TYPE_VIRTUAL *Type:* VARIABLE Debug type virtual. ### DEBUG_DISPLAY_TIMESTAMPS *Type:* VARIABLE Debug display timestamps. ### DEBUG_DISPLAY_LINENUMBERS *Type:* VARIABLE Debug display linenumbers. ### DEBUG_DISPLAY_THREAD *Type:* VARIABLE Debug display thread. ### MEMORY_NORMAL *Type:* VARIABLE Memory normal. ### MEMORY_STREAM_FILE *Type:* VARIABLE Memory stream file. ### MEMORY_STREAM_DECODE *Type:* VARIABLE Memory stream decode. ### MEMORY_SAMPLEDATA *Type:* VARIABLE Memory sampledata. ### MEMORY_DSP_BUFFER *Type:* VARIABLE Memory dsp buffer. ### MEMORY_PLUGIN *Type:* VARIABLE Memory plugin. ### MEMORY_PERSISTENT *Type:* VARIABLE Memory persistent. ### MEMORY_ALL *Type:* VARIABLE Memory all. ### INIT_NORMAL *Type:* VARIABLE Init normal. ### INIT_STREAM_FROM_UPDATE *Type:* VARIABLE Init stream from update. ### INIT_MIX_FROM_UPDATE *Type:* VARIABLE Init mix from update. ### INIT_3D_RIGHTHANDED *Type:* VARIABLE Init 3d righthanded. ### INIT_CLIP_OUTPUT *Type:* VARIABLE Init clip output. ### INIT_CHANNEL_LOWPASS *Type:* VARIABLE Init channel lowpass. ### INIT_CHANNEL_DISTANCEFILTER *Type:* VARIABLE Init channel distancefilter. ### INIT_PROFILE_ENABLE *Type:* VARIABLE Init profile enable. ### INIT_VOL0_BECOMES_VIRTUAL *Type:* VARIABLE Init vol0 becomes virtual. ### INIT_GEOMETRY_USECLOSEST *Type:* VARIABLE Init geometry useclosest. ### INIT_PREFER_DOLBY_DOWNMIX *Type:* VARIABLE Init prefer dolby downmix. ### INIT_THREAD_UNSAFE *Type:* VARIABLE Init thread unsafe. ### INIT_PROFILE_METER_ALL *Type:* VARIABLE Init profile meter all. ### INIT_MEMORY_TRACKING *Type:* VARIABLE Init memory tracking. ### DRIVER_STATE_CONNECTED *Type:* VARIABLE Driver state - connected. ### DRIVER_STATE_DEFAULT *Type:* VARIABLE Driver state - default. ### TIMEUNIT_MS *Type:* VARIABLE Time unit - ms. ### TIMEUNIT_PCM *Type:* VARIABLE Time unit - pcm. ### TIMEUNIT_PCMBYTES *Type:* VARIABLE Time unit - pcmbytes. ### TIMEUNIT_RAWBYTES *Type:* VARIABLE Time unit - rawbytes. ### TIMEUNIT_PCMFRACTION *Type:* VARIABLE Time unit - pcmfraction. ### TIMEUNIT_MODORDER *Type:* VARIABLE Time unit - modorder. ### TIMEUNIT_MODROW *Type:* VARIABLE Time unit - modrow. ### TIMEUNIT_MODPATTERN *Type:* VARIABLE Time unit - modpattern. ### SYSTEM_CALLBACK_DEVICELISTCHANGED *Type:* VARIABLE System callback devicelistchanged. ### SYSTEM_CALLBACK_DEVICELOST *Type:* VARIABLE System callback devicelost. ### SYSTEM_CALLBACK_MEMORYALLOCATIONFAILED *Type:* VARIABLE System callback memoryallocationfailed. ### SYSTEM_CALLBACK_THREADCREATED *Type:* VARIABLE System callback threadcreated. ### SYSTEM_CALLBACK_BADDSPCONNECTION *Type:* VARIABLE System callback baddspconnection. ### SYSTEM_CALLBACK_PREMIX *Type:* VARIABLE System callback premix. ### SYSTEM_CALLBACK_POSTMIX *Type:* VARIABLE System callback postmix. ### SYSTEM_CALLBACK_ERROR *Type:* VARIABLE System callback error. ### SYSTEM_CALLBACK_THREADDESTROYED *Type:* VARIABLE System callback threaddestroyed. ### SYSTEM_CALLBACK_PREUPDATE *Type:* VARIABLE System callback preupdate. ### SYSTEM_CALLBACK_POSTUPDATE *Type:* VARIABLE System callback postupdate. ### SYSTEM_CALLBACK_RECORDLISTCHANGED *Type:* VARIABLE System callback recordlistchanged. ### SYSTEM_CALLBACK_BUFFEREDNOMIX *Type:* VARIABLE System callback bufferednomix. ### SYSTEM_CALLBACK_DEVICEREINITIALIZE *Type:* VARIABLE System callback devicereinitialize. ### SYSTEM_CALLBACK_OUTPUTUNDERRUN *Type:* VARIABLE System callback outputunderrun. ### SYSTEM_CALLBACK_RECORDPOSITIONCHANGED *Type:* VARIABLE System callback recordpositionchanged. ### SYSTEM_CALLBACK_ALL *Type:* VARIABLE System callback all. ### DEFAULT *Type:* VARIABLE Default. ### LOOP_OFF *Type:* VARIABLE Loop off. ### LOOP_NORMAL *Type:* VARIABLE Loop normal. ### LOOP_BIDI *Type:* VARIABLE Loop bidi. ### 2D *Type:* VARIABLE 2d. ### 3D *Type:* VARIABLE 3d. ### CREATESTREAM *Type:* VARIABLE Createstream. ### CREATESAMPLE *Type:* VARIABLE Createsample. ### CREATECOMPRESSEDSAMPLE *Type:* VARIABLE Createcompressedsample. ### OPENUSER *Type:* VARIABLE Openuser. ### OPENMEMORY *Type:* VARIABLE Openmemory. ### OPENMEMORY_POINT *Type:* VARIABLE Openmemory point. ### OPENRAW *Type:* VARIABLE Openraw. ### OPENONLY *Type:* VARIABLE Openonly. ### ACCURATETIME *Type:* VARIABLE Accuratetime. ### MPEGSEARCH *Type:* VARIABLE Mpegsearch. ### NONBLOCKING *Type:* VARIABLE Nonblocking. ### UNIQUE *Type:* VARIABLE Unique. ### 3D_HEADRELATIVE *Type:* VARIABLE 3d headrelative. ### 3D_WORLDRELATIVE *Type:* VARIABLE 3d worldrelative. ### 3D_INVERSEROLLOFF *Type:* VARIABLE 3d inverserolloff. ### 3D_LINEARROLLOFF *Type:* VARIABLE 3d linearrolloff. ### 3D_LINEARSQUAREROLLOFF *Type:* VARIABLE 3d linearsquarerolloff. ### 3D_INVERSETAPEREDROLLOFF *Type:* VARIABLE 3d inversetaperedrolloff. ### 3D_CUSTOMROLLOFF *Type:* VARIABLE 3d customrolloff. ### 3D_IGNOREGEOMETRY *Type:* VARIABLE 3d ignoregeometry. ### IGNORETAGS *Type:* VARIABLE Ignoretags. ### LOWMEM *Type:* VARIABLE Lowmem. ### VIRTUAL_PLAYFROMSTART *Type:* VARIABLE Virtual playfromstart. ### CHANNELMASK_FRONT_LEFT *Type:* VARIABLE Channelmask front left. ### CHANNELMASK_FRONT_RIGHT *Type:* VARIABLE Channelmask front right. ### CHANNELMASK_FRONT_CENTER *Type:* VARIABLE Channelmask front center. ### CHANNELMASK_LOW_FREQUENCY *Type:* VARIABLE Channelmask low frequency. ### CHANNELMASK_SURROUND_LEFT *Type:* VARIABLE Channelmask surround left. ### CHANNELMASK_SURROUND_RIGHT *Type:* VARIABLE Channelmask surround right. ### CHANNELMASK_BACK_LEFT *Type:* VARIABLE Channelmask back left. ### CHANNELMASK_BACK_RIGHT *Type:* VARIABLE Channelmask back right. ### CHANNELMASK_BACK_CENTER *Type:* VARIABLE Channelmask back center. ### CHANNELMASK_MONO *Type:* VARIABLE Channelmask mono. ### CHANNELMASK_STEREO *Type:* VARIABLE Channelmask stereo. ### CHANNELMASK_LRC *Type:* VARIABLE Channelmask lrc. ### CHANNELMASK_QUAD *Type:* VARIABLE Channelmask quad. ### CHANNELMASK_SURROUND *Type:* VARIABLE Channelmask surround. ### CHANNELMASK_5POINT1 *Type:* VARIABLE Channelmask 5point1. ### CHANNELMASK_5POINT1_REARS *Type:* VARIABLE Channelmask 5point1 rears. ### CHANNELMASK_7POINT0 *Type:* VARIABLE Channelmask 7point0. ### CHANNELMASK_7POINT1 *Type:* VARIABLE Channelmask 7point1. ### PORT_INDEX_NONE *Type:* VARIABLE Port index none. ### THREAD_PRIORITY_PLATFORM_MIN *Type:* VARIABLE Thread priority - platform min. ### THREAD_PRIORITY_PLATFORM_MAX *Type:* VARIABLE Thread priority - platform max. ### THREAD_PRIORITY_DEFAULT *Type:* VARIABLE Thread priority - default. ### THREAD_PRIORITY_LOW *Type:* VARIABLE Thread priority - low. ### THREAD_PRIORITY_MEDIUM *Type:* VARIABLE Thread priority - medium. ### THREAD_PRIORITY_HIGH *Type:* VARIABLE Thread priority - high. ### THREAD_PRIORITY_VERY_HIGH *Type:* VARIABLE Thread priority - very high. ### THREAD_PRIORITY_EXTREME *Type:* VARIABLE Thread priority - extreme. ### THREAD_PRIORITY_CRITICAL *Type:* VARIABLE Thread priority - critical. ### THREAD_PRIORITY_MIXER *Type:* VARIABLE Thread priority - mixer. ### THREAD_PRIORITY_FEEDER *Type:* VARIABLE Thread priority - feeder. ### THREAD_PRIORITY_STREAM *Type:* VARIABLE Thread priority - stream. ### THREAD_PRIORITY_FILE *Type:* VARIABLE Thread priority - file. ### THREAD_PRIORITY_NONBLOCKING *Type:* VARIABLE Thread priority - nonblocking. ### THREAD_PRIORITY_RECORD *Type:* VARIABLE Thread priority - record. ### THREAD_PRIORITY_GEOMETRY *Type:* VARIABLE Thread priority - geometry. ### THREAD_PRIORITY_PROFILER *Type:* VARIABLE Thread priority - profiler. ### THREAD_PRIORITY_STUDIO_UPDATE *Type:* VARIABLE Thread priority - studio update. ### THREAD_PRIORITY_STUDIO_LOAD_BANK *Type:* VARIABLE Thread priority - studio load bank. ### THREAD_PRIORITY_STUDIO_LOAD_SAMPLE *Type:* VARIABLE Thread priority - studio load sample. ### THREAD_PRIORITY_CONVOLUTION1 *Type:* VARIABLE Thread priority - convolution1. ### THREAD_PRIORITY_CONVOLUTION2 *Type:* VARIABLE Thread priority - convolution2. ### THREAD_STACK_SIZE_DEFAULT *Type:* VARIABLE Thread stack size - default. ### THREAD_STACK_SIZE_MIXER *Type:* VARIABLE Thread stack size - mixer. ### THREAD_STACK_SIZE_FEEDER *Type:* VARIABLE Thread stack size - feeder. ### THREAD_STACK_SIZE_STREAM *Type:* VARIABLE Thread stack size - stream. ### THREAD_STACK_SIZE_FILE *Type:* VARIABLE Thread stack size - file. ### THREAD_STACK_SIZE_NONBLOCKING *Type:* VARIABLE Thread stack size - nonblocking. ### THREAD_STACK_SIZE_RECORD *Type:* VARIABLE Thread stack size - record. ### THREAD_STACK_SIZE_GEOMETRY *Type:* VARIABLE Thread stack size - geometry. ### THREAD_STACK_SIZE_PROFILER *Type:* VARIABLE Thread stack size - profiler. ### THREAD_STACK_SIZE_STUDIO_UPDATE *Type:* VARIABLE Thread stack size - studio update. ### THREAD_STACK_SIZE_STUDIO_LOAD_BANK *Type:* VARIABLE Thread stack size - studio load bank. ### THREAD_STACK_SIZE_STUDIO_LOAD_SAMPLE *Type:* VARIABLE Thread stack size - studio load sample. ### THREAD_STACK_SIZE_CONVOLUTION1 *Type:* VARIABLE Thread stack size - convolution1. ### THREAD_STACK_SIZE_CONVOLUTION2 *Type:* VARIABLE Thread stack size - convolution2. ### THREAD_AFFINITY_GROUP_DEFAULT *Type:* VARIABLE Thread affinity - group default. ### THREAD_AFFINITY_GROUP_A *Type:* VARIABLE Thread affinity - group a. ### THREAD_AFFINITY_GROUP_B *Type:* VARIABLE Thread affinity - group b. ### THREAD_AFFINITY_GROUP_C *Type:* VARIABLE Thread affinity - group c. ### THREAD_AFFINITY_MIXER *Type:* VARIABLE Thread affinity - mixer. ### THREAD_AFFINITY_FEEDER *Type:* VARIABLE Thread affinity - feeder. ### THREAD_AFFINITY_STREAM *Type:* VARIABLE Thread affinity - stream. ### THREAD_AFFINITY_FILE *Type:* VARIABLE Thread affinity - file. ### THREAD_AFFINITY_NONBLOCKING *Type:* VARIABLE Thread affinity - nonblocking. ### THREAD_AFFINITY_RECORD *Type:* VARIABLE Thread affinity - record. ### THREAD_AFFINITY_GEOMETRY *Type:* VARIABLE Thread affinity - geometry. ### THREAD_AFFINITY_PROFILER *Type:* VARIABLE Thread affinity - profiler. ### THREAD_AFFINITY_STUDIO_UPDATE *Type:* VARIABLE Thread affinity - studio update. ### THREAD_AFFINITY_STUDIO_LOAD_BANK *Type:* VARIABLE Thread affinity - studio load bank. ### THREAD_AFFINITY_STUDIO_LOAD_SAMPLE *Type:* VARIABLE Thread affinity - studio load sample. ### THREAD_AFFINITY_CONVOLUTION1 *Type:* VARIABLE Thread affinity - convolution1. ### THREAD_AFFINITY_CONVOLUTION2 *Type:* VARIABLE Thread affinity - convolution2. ### THREAD_AFFINITY_CORE_ALL *Type:* VARIABLE Thread affinity - core all. ### THREAD_AFFINITY_CORE_0 *Type:* VARIABLE Thread affinity - core 0. ### THREAD_AFFINITY_CORE_1 *Type:* VARIABLE Thread affinity - core 1. ### THREAD_AFFINITY_CORE_2 *Type:* VARIABLE Thread affinity - core 2. ### THREAD_AFFINITY_CORE_3 *Type:* VARIABLE Thread affinity - core 3. ### THREAD_AFFINITY_CORE_4 *Type:* VARIABLE Thread affinity - core 4. ### THREAD_AFFINITY_CORE_5 *Type:* VARIABLE Thread affinity - core 5. ### THREAD_AFFINITY_CORE_6 *Type:* VARIABLE Thread affinity - core 6. ### THREAD_AFFINITY_CORE_7 *Type:* VARIABLE Thread affinity - core 7. ### THREAD_AFFINITY_CORE_8 *Type:* VARIABLE Thread affinity - core 8. ### THREAD_AFFINITY_CORE_9 *Type:* VARIABLE Thread affinity - core 9. ### THREAD_AFFINITY_CORE_10 *Type:* VARIABLE Thread affinity - core 10. ### THREAD_AFFINITY_CORE_11 *Type:* VARIABLE Thread affinity - core 11. ### THREAD_AFFINITY_CORE_12 *Type:* VARIABLE Thread affinity - core 12. ### THREAD_AFFINITY_CORE_13 *Type:* VARIABLE Thread affinity - core 13. ### THREAD_AFFINITY_CORE_14 *Type:* VARIABLE Thread affinity - core 14. ### THREAD_AFFINITY_CORE_15 *Type:* VARIABLE Thread affinity - core 15. ### MAX_CHANNEL_WIDTH *Type:* VARIABLE Max channel width. ### MAX_SYSTEMS *Type:* VARIABLE Max systems. ### MAX_LISTENERS *Type:* VARIABLE Max listeners. ### REVERB_MAXINSTANCES *Type:* VARIABLE Reverb maxinstances. ### STUDIO_LOAD_MEMORY_ALIGNMENT *Type:* VARIABLE Studio load memory alignment. ### STUDIO_INIT_NORMAL *Type:* VARIABLE Studio init normal. ### STUDIO_INIT_LIVEUPDATE *Type:* VARIABLE Studio init liveupdate. ### STUDIO_INIT_ALLOW_MISSING_PLUGINS *Type:* VARIABLE Studio init allow missing plugins. ### STUDIO_INIT_SYNCHRONOUS_UPDATE *Type:* VARIABLE Studio init synchronous update. ### STUDIO_INIT_DEFERRED_CALLBACKS *Type:* VARIABLE Studio init deferred callbacks. ### STUDIO_INIT_LOAD_FROM_UPDATE *Type:* VARIABLE Studio init load from update. ### STUDIO_INIT_MEMORY_TRACKING *Type:* VARIABLE Studio init memory tracking. ### STUDIO_PARAMETER_READONLY *Type:* VARIABLE Studio parameter type - readonly. ### STUDIO_PARAMETER_AUTOMATIC *Type:* VARIABLE Studio parameter type - automatic. ### STUDIO_PARAMETER_GLOBAL *Type:* VARIABLE Studio parameter type - global. ### STUDIO_PARAMETER_DISCRETE *Type:* VARIABLE Studio parameter type - discrete. ### STUDIO_PARAMETER_LABELED *Type:* VARIABLE Studio parameter type - labeled. ### STUDIO_SYSTEM_CALLBACK_PREUPDATE *Type:* VARIABLE System callback type - preupdate. ### STUDIO_SYSTEM_CALLBACK_POSTUPDATE *Type:* VARIABLE System callback type - postupdate. ### STUDIO_SYSTEM_CALLBACK_BANK_UNLOAD *Type:* VARIABLE System callback type - bank unload. ### STUDIO_SYSTEM_CALLBACK_LIVEUPDATE_CONNECTED *Type:* VARIABLE System callback type - liveupdate connected. ### STUDIO_SYSTEM_CALLBACK_LIVEUPDATE_DISCONNECTED *Type:* VARIABLE System callback type - liveupdate disconnected. ### STUDIO_SYSTEM_CALLBACK_ALL *Type:* VARIABLE System callback type - all. ### STUDIO_EVENT_CALLBACK_CREATED *Type:* VARIABLE Event callback type - created. ### STUDIO_EVENT_CALLBACK_DESTROYED *Type:* VARIABLE Event callback type - destroyed. ### STUDIO_EVENT_CALLBACK_STARTING *Type:* VARIABLE Event callback type - starting. ### STUDIO_EVENT_CALLBACK_STARTED *Type:* VARIABLE Event callback type - started. ### STUDIO_EVENT_CALLBACK_RESTARTED *Type:* VARIABLE Event callback type - restarted. ### STUDIO_EVENT_CALLBACK_STOPPED *Type:* VARIABLE Event callback type - stopped. ### STUDIO_EVENT_CALLBACK_START_FAILED *Type:* VARIABLE Event callback type - start failed. ### STUDIO_EVENT_CALLBACK_CREATE_PROGRAMMER_SOUND *Type:* VARIABLE Event callback type - create programmer sound. ### STUDIO_EVENT_CALLBACK_DESTROY_PROGRAMMER_SOUND *Type:* VARIABLE Event callback type - destroy programmer sound. ### STUDIO_EVENT_CALLBACK_PLUGIN_CREATED *Type:* VARIABLE Event callback type - plugin created. ### STUDIO_EVENT_CALLBACK_PLUGIN_DESTROYED *Type:* VARIABLE Event callback type - plugin destroyed. ### STUDIO_EVENT_CALLBACK_TIMELINE_MARKER *Type:* VARIABLE Event callback type - timeline marker. ### STUDIO_EVENT_CALLBACK_TIMELINE_BEAT *Type:* VARIABLE Event callback type - timeline beat. ### STUDIO_EVENT_CALLBACK_SOUND_PLAYED *Type:* VARIABLE Event callback type - sound played. ### STUDIO_EVENT_CALLBACK_SOUND_STOPPED *Type:* VARIABLE Event callback type - sound stopped. ### STUDIO_EVENT_CALLBACK_REAL_TO_VIRTUAL *Type:* VARIABLE Event callback type - real to virtual. ### STUDIO_EVENT_CALLBACK_VIRTUAL_TO_REAL *Type:* VARIABLE Event callback type - virtual to real. ### STUDIO_EVENT_CALLBACK_START_EVENT_COMMAND *Type:* VARIABLE Event callback type - start event command. ### STUDIO_EVENT_CALLBACK_NESTED_TIMELINE_BEAT *Type:* VARIABLE Event callback type - nested timeline beat. ### STUDIO_EVENT_CALLBACK_ALL *Type:* VARIABLE Event callback type - all. ### STUDIO_LOAD_BANK_NORMAL *Type:* VARIABLE Bank loading mode - normal. ### STUDIO_LOAD_BANK_NONBLOCKING *Type:* VARIABLE Bank loading mode - nonblocking. ### STUDIO_LOAD_BANK_DECOMPRESS_SAMPLES *Type:* VARIABLE Bank loading mode - decompress samples. ### STUDIO_LOAD_BANK_UNENCRYPTED *Type:* VARIABLE Bank loading mode - unencrypted. ### STUDIO_COMMANDCAPTURE_NORMAL *Type:* VARIABLE Studio commandcapture normal. ### STUDIO_COMMANDCAPTURE_FILEFLUSH *Type:* VARIABLE Studio commandcapture fileflush. ### STUDIO_COMMANDCAPTURE_SKIP_INITIAL_STATE *Type:* VARIABLE Studio commandcapture skip initial state. ### STUDIO_COMMANDREPLAY_NORMAL *Type:* VARIABLE Studio commandreplay normal. ### STUDIO_COMMANDREPLAY_SKIP_CLEANUP *Type:* VARIABLE Studio commandreplay skip cleanup. ### STUDIO_COMMANDREPLAY_FAST_FORWARD *Type:* VARIABLE Studio commandreplay fast forward. ### STUDIO_COMMANDREPLAY_SKIP_BANK_LOAD *Type:* VARIABLE Studio commandreplay skip bank load. ### fmod.ASYNCREADINFO *Type:* FUNCTION Creates a new FMOD_ASYNCREADINFO struct **Returns** - `fmod.asyncreadinfo` - The created struct instance ### fmod._3D_ATTRIBUTES *Type:* FUNCTION Creates a new FMOD_3D_ATTRIBUTES struct **Returns** - `fmod.3d_attributes` - The created struct instance ### fmod.GUID *Type:* FUNCTION Creates a new FMOD_GUID struct **Returns** - `fmod.guid` - The created struct instance ### fmod.PLUGINLIST *Type:* FUNCTION Creates a new FMOD_PLUGINLIST struct **Returns** - `fmod.pluginlist` - The created struct instance ### fmod.ADVANCEDSETTINGS *Type:* FUNCTION Creates a new FMOD_ADVANCEDSETTINGS struct **Returns** - `fmod.advancedsettings` - The created struct instance ### fmod.TAG *Type:* FUNCTION Creates a new FMOD_TAG struct **Returns** - `fmod.tag` - The created struct instance ### fmod.CREATESOUNDEXINFO *Type:* FUNCTION Creates a new FMOD_CREATESOUNDEXINFO struct **Returns** - `fmod.createsoundexinfo` - The created struct instance ### fmod.REVERB_PROPERTIES *Type:* FUNCTION Creates a new FMOD_REVERB_PROPERTIES struct **Returns** - `fmod.reverb_properties` - The created struct instance ### fmod.ERRORCALLBACK_INFO *Type:* FUNCTION Creates a new FMOD_ERRORCALLBACK_INFO struct **Returns** - `fmod.errorcallback_info` - The created struct instance ### fmod.CPU_USAGE *Type:* FUNCTION Creates a new FMOD_CPU_USAGE struct **Returns** - `fmod.cpu_usage` - The created struct instance ### fmod.DSP_DATA_PARAMETER_INFO *Type:* FUNCTION Creates a new FMOD_DSP_DATA_PARAMETER_INFO struct **Returns** - `fmod.dsp_data_parameter_info` - The created struct instance ### fmod.CODEC_STATE *Type:* FUNCTION Creates a new FMOD_CODEC_STATE struct **Returns** - `fmod.codec_state` - The created struct instance ### fmod.CODEC_WAVEFORMAT *Type:* FUNCTION Creates a new FMOD_CODEC_WAVEFORMAT struct **Returns** - `fmod.codec_waveformat` - The created struct instance ### fmod.CODEC_DESCRIPTION *Type:* FUNCTION Creates a new FMOD_CODEC_DESCRIPTION struct **Returns** - `fmod.codec_description` - The created struct instance ### fmod.CODEC_STATE_FUNCTIONS *Type:* FUNCTION Creates a new FMOD_CODEC_STATE_FUNCTIONS struct **Returns** - `fmod.codec_state_functions` - The created struct instance ### fmod.DSP_LOUDNESS_METER_INFO_TYPE *Type:* FUNCTION Creates a new FMOD_DSP_LOUDNESS_METER_INFO_TYPE struct **Returns** - `fmod.dsp_loudness_meter_info_type` - The created struct instance ### fmod.DSP_LOUDNESS_METER_WEIGHTING_TYPE *Type:* FUNCTION Creates a new FMOD_DSP_LOUDNESS_METER_WEIGHTING_TYPE struct **Returns** - `fmod.dsp_loudness_meter_weighting_type` - The created struct instance ### fmod.DSP_STATE *Type:* FUNCTION Creates a new FMOD_DSP_STATE struct **Returns** - `fmod.dsp_state` - The created struct instance ### fmod.DSP_BUFFER_ARRAY *Type:* FUNCTION Creates a new FMOD_DSP_BUFFER_ARRAY struct **Returns** - `fmod.dsp_buffer_array` - The created struct instance ### fmod.COMPLEX *Type:* FUNCTION Creates a new FMOD_COMPLEX struct **Returns** - `fmod.complex` - The created struct instance ### fmod.DSP_PARAMETER_FLOAT_MAPPING_PIECEWISE_LINEAR *Type:* FUNCTION Creates a new FMOD_DSP_PARAMETER_FLOAT_MAPPING_PIECEWISE_LINEAR struct **Returns** - `fmod.dsp_parameter_float_mapping_piecewise_linear` - The created struct instance ### fmod.DSP_PARAMETER_FLOAT_MAPPING *Type:* FUNCTION Creates a new FMOD_DSP_PARAMETER_FLOAT_MAPPING struct **Returns** - `fmod.dsp_parameter_float_mapping` - The created struct instance ### fmod.DSP_PARAMETER_DESC_FLOAT *Type:* FUNCTION Creates a new FMOD_DSP_PARAMETER_DESC_FLOAT struct **Returns** - `fmod.dsp_parameter_desc_float` - The created struct instance ### fmod.DSP_PARAMETER_DESC_INT *Type:* FUNCTION Creates a new FMOD_DSP_PARAMETER_DESC_INT struct **Returns** - `fmod.dsp_parameter_desc_int` - The created struct instance ### fmod.DSP_PARAMETER_DESC_BOOL *Type:* FUNCTION Creates a new FMOD_DSP_PARAMETER_DESC_BOOL struct **Returns** - `fmod.dsp_parameter_desc_bool` - The created struct instance ### fmod.DSP_PARAMETER_DESC_DATA *Type:* FUNCTION Creates a new FMOD_DSP_PARAMETER_DESC_DATA struct **Returns** - `fmod.dsp_parameter_desc_data` - The created struct instance ### fmod.DSP_PARAMETER_DESC *Type:* FUNCTION Creates a new FMOD_DSP_PARAMETER_DESC struct **Returns** - `fmod.dsp_parameter_desc` - The created struct instance ### fmod.DSP_PARAMETER_OVERALLGAIN *Type:* FUNCTION Creates a new FMOD_DSP_PARAMETER_OVERALLGAIN struct **Returns** - `fmod.dsp_parameter_overallgain` - The created struct instance ### fmod.DSP_PARAMETER_3DATTRIBUTES *Type:* FUNCTION Creates a new FMOD_DSP_PARAMETER_3DATTRIBUTES struct **Returns** - `fmod.dsp_parameter_3dattributes` - The created struct instance ### fmod.DSP_PARAMETER_3DATTRIBUTES_MULTI *Type:* FUNCTION Creates a new FMOD_DSP_PARAMETER_3DATTRIBUTES_MULTI struct **Returns** - `fmod.dsp_parameter_3dattributes_multi` - The created struct instance ### fmod.DSP_PARAMETER_ATTENUATION_RANGE *Type:* FUNCTION Creates a new FMOD_DSP_PARAMETER_ATTENUATION_RANGE struct **Returns** - `fmod.dsp_parameter_attenuation_range` - The created struct instance ### fmod.DSP_PARAMETER_SIDECHAIN *Type:* FUNCTION Creates a new FMOD_DSP_PARAMETER_SIDECHAIN struct **Returns** - `fmod.dsp_parameter_sidechain` - The created struct instance ### fmod.DSP_PARAMETER_FFT *Type:* FUNCTION Creates a new FMOD_DSP_PARAMETER_FFT struct **Returns** - `fmod.dsp_parameter_fft` - The created struct instance ### fmod.DSP_PARAMETER_DYNAMIC_RESPONSE *Type:* FUNCTION Creates a new FMOD_DSP_PARAMETER_DYNAMIC_RESPONSE struct **Returns** - `fmod.dsp_parameter_dynamic_response` - The created struct instance ### fmod.DSP_DESCRIPTION *Type:* FUNCTION Creates a new FMOD_DSP_DESCRIPTION struct **Returns** - `fmod.dsp_description` - The created struct instance ### fmod.DSP_STATE_DFT_FUNCTIONS *Type:* FUNCTION Creates a new FMOD_DSP_STATE_DFT_FUNCTIONS struct **Returns** - `fmod.dsp_state_dft_functions` - The created struct instance ### fmod.DSP_STATE_PAN_FUNCTIONS *Type:* FUNCTION Creates a new FMOD_DSP_STATE_PAN_FUNCTIONS struct **Returns** - `fmod.dsp_state_pan_functions` - The created struct instance ### fmod.DSP_STATE_FUNCTIONS *Type:* FUNCTION Creates a new FMOD_DSP_STATE_FUNCTIONS struct **Returns** - `fmod.dsp_state_functions` - The created struct instance ### fmod.DSP_METERING_INFO *Type:* FUNCTION Creates a new FMOD_DSP_METERING_INFO struct **Returns** - `fmod.dsp_metering_info` - The created struct instance ### fmod.OUTPUT_STATE *Type:* FUNCTION Creates a new FMOD_OUTPUT_STATE struct **Returns** - `fmod.output_state` - The created struct instance ### fmod.OUTPUT_OBJECT3DINFO *Type:* FUNCTION Creates a new FMOD_OUTPUT_OBJECT3DINFO struct **Returns** - `fmod.output_object3dinfo` - The created struct instance ### fmod.OUTPUT_DESCRIPTION *Type:* FUNCTION Creates a new FMOD_OUTPUT_DESCRIPTION struct **Returns** - `fmod.output_description` - The created struct instance ### fmod.memory_initialize *Type:* FUNCTION Initialize for memory. ### fmod.memory_get_stats *Type:* FUNCTION Get stats for memory. **Parameters** - `blocking` (boolean) - Bool value **Returns** - `userdata` - The currentalloced value - `userdata` - The maxalloced value ### fmod.debug_initialize *Type:* FUNCTION Initialize for debug. ### fmod.file_set_disk_busy *Type:* FUNCTION Set disk busy for file. **Parameters** - `busy` (number) - Bus handle ### fmod.file_get_disk_busy *Type:* FUNCTION Get disk busy for file. **Returns** - `userdata` - The busy value ### fmod.thread_set_attributes *Type:* FUNCTION Set attributes for thread. **Parameters** - `type` (number) - Type value - `affinity` (number) - Affinity value - `priority` (number) - Priority (0 = highest, 256 = lowest) - `stacksize` (number) - Size value ### fmod.system_create *Type:* FUNCTION Create for system. **Parameters** - `headerversion` (number) - headerversion **Returns** - `userdata` - The system value ### system *Type:* FMOD.SYSTEM The FMOD low-level system instance ### *Type:* TABLE Table mapping error messages to error codes ### fmod.s64 *Type:* FUNCTION Creates a signed 64-bit integer value **Parameters** - `value` (number) - The value (or low 32 bits if high is provided) - `high` (number) - The high 32 bits (optional) **Returns** - `userdata` - The 64-bit integer value ### fmod.u64 *Type:* FUNCTION Creates an unsigned 64-bit integer value **Parameters** - `value` (number) - The value (or low 32 bits if high is provided) - `high` (number) - The high 32 bits (optional) **Returns** - `userdata` - The 64-bit integer value # extension-fontgen {#apis:extension-fontgen_fontgen} **Namespace:** `fontgen` **Language:** Lua **Type:** Extension Functions to generate glyphs for fonts at runtime. ## API ### fontgen.load_font *Type:* FUNCTION Creates a mapping between a .fontc file and a .ttf file. Increases the ref count for both resources. **Parameters** - `fontc_path` (string) - Path to a .fontc file in the project - `ttf_path` (string) - Path to a .ttf file in the project - `options` (table) - Options for generating the glyphs - `sdf_padding` (number) - The number of padding pixels [0-255] - `sdf_edge` (number) - Where the edge is decided to be [0-255] - `complete_function` (function) - function to call when the animation has completed - `self` (object) - The context of the calling script - `fontc_hash` (hash) - The path hash of the .fontc resource ### fontgen.unload_font *Type:* FUNCTION Removes the generator mapping between the .fontc and .ttf file. Decreases the ref count for both resources. Does not remove the previously generated glyphs! **Parameters** - `fontc_path_hash` (hash) - Path hash of the .fontc file in the project ### fontgen.add_glyphs *Type:* FUNCTION Asynchronoously sdds glyphs to the .fontc resource. **Parameters** - `fontc_path_hash` (hash) - Path hash of the .fontc file in the project - `text` (string) - Utf-8 string containing glyphs to add to the .fontc *Note* No checks for duplicate glyphs is done. - `callback` (function) - Function to be called after the last glyph was processed. May be nil. - `self` (object) - The script instance that called `add_glyphs` - `request` (int) - The request id returned by `add_glyphs` - `result` (bool) - True if all glyphs were added successfully - `errmsg` (string) - Error string if a glyph wasn't generated or added successfully **Returns** - `integer` - Returns a request id, used in the callback ### fontgen.remove_glyphs *Type:* FUNCTION Removes glyphs from the .fontc resource **Parameters** - `fontc_path_hash` (hash) - Path hash of the .fontc file in the project - `text` (string) - Utf-8 string containing glyphs to remove from the .fontc # extension-googleplayinstant {#apis:extension-googleplayinstant_instantapp} **Namespace:** `instantapp` **Language:** Lua **Type:** Extension Functions and constants for interacting with InstantApp APIs ## API ### instantapp.show_install_prompt *Type:* FUNCTION Shows a dialog that allows the user to install the current instant app. ### instantapp.is_instant_app *Type:* FUNCTION Checks if application loaded as instant experience. **Returns** - `boolean` - Returns true if this application is an instant app. ### instantapp.get_cookie_max_size *Type:* FUNCTION Gets the maximum size in bytes of the cookie data an instant app can store on the device. **Returns** - `number` - The maximum size in bytes of the cookie data an instant app can store on the device. ### instantapp.get_cookie *Type:* FUNCTION Load byte array from cookies that were saved in instant application. **Returns** - `string` - The byte array data of cookies saved in instant application. ### instantapp.set_cookie *Type:* FUNCTION Save byte array in cookies to be able get access to this data in installable application. **Parameters** - `bytes` (string) - The byte array data will be saved in cookies for access in installable application. # extension-gpgs {#apis:extension-gpgs_gpgs} **Namespace:** `gpgs` **Language:** Lua **Type:** Extension Functions and constants for interacting with Google Play Game Services (GPGS) APIs ## API ### gpgs.is_supported *Type:* FUNCTION Check if Google Play Services are available & ready on the device. **Returns** - `boolean` - Status of Google Play Services on the device. **Examples** ``` if gpgs then local is_supported = gpgs.is_supported() end ``` ### gpgs.login *Type:* FUNCTION Login to GPGS using a button. **Examples** Log in to GPGS using a button: ``` if gpgs then gpgs.login() end ``` ### gpgs.silent_login *Type:* FUNCTION Silent login to GPGS. This function is trying to retrieve the currently signed-in player’s account. **Examples** ``` function init(self) if gpgs then gpgs.silent_login() end end ``` ### gpgs.get_display_name *Type:* FUNCTION Get the current GPGS player display name. **Returns** - `string` - The player's display name. **Examples** ``` if gpgs then local name = gpgs.get_display_name() end ``` ### gpgs.get_id *Type:* FUNCTION Get the current GPGS player id. **Returns** - `string` - The player ID. **Examples** ``` if gpgs then local id = gpgs.get_id() end ``` ### gpgs.get_server_auth_code *Type:* FUNCTION Returns a one-time server auth code to send to your web server which can be exchanged for access token Token can be retrieved only if `gpgs.request_server_auth_code` set to 1 and `gpgs.client` is set. **Returns** - `string` - The server auth code for logged in account. Can be nil if operation is not completed yet. Auth token is avaliable after receiving message with id `gpgs.MSG_GET_SERVER_TOKEN` in callback set via `gpgs.set_callback`. **Examples** ``` if gpgs then local server_auth_code = gpgs.get_server_auth_code() end ``` ### gpgs.is_logged_in *Type:* FUNCTION Check if a user is logged in currently. **Returns** - `boolean` - Current login state. **Examples** ``` if gpgs then local is_loggedin = gpgs.is_logged_in() end ``` ### gpgs.set_callback *Type:* FUNCTION Set callback for receiving messages from GPGS. **Parameters** - `callback` (function) - A callback taking the following parameters - `self` (object) - The calling script - `message_id` (number) - An message_id can be one of the predefined constants below - `gpgs.MSG_SIGN_IN` - `gpgs.MSG_SILENT_SIGN_IN` - `gpgs.MSG_SHOW_SNAPSHOTS` - `gpgs.MSG_LOAD_SNAPSHOT` - `gpgs.MSG_SAVE_SNAPSHOT` - `message` (table) - Contains information that depends on message_id. - `status` (number) - Status of the current operation. It can be one of the predefined constants below - `gpgs.STATUS_SUCCESS` - `gpgs.STATUS_FAILED` - `gpgs.STATUS_CREATE_NEW_SAVE` - `gpgs.STATUS_CONFLICT` - `error` (string) - The error message. Available only if `status` is `gpgs.STATUS_FAILED`. - `error_status` (number) - The error code. Available only if `status` is `gpgs.STATUS_FAILED` and GPGS provide this code. It can be one of the predefined constants below - `gpgs.ERROR_STATUS_SNAPSHOT_COMMIT_FAILED` - `gpgs.ERROR_STATUS_SNAPSHOT_CONFLICT_MISSING` - `gpgs.ERROR_STATUS_SNAPSHOT_CONTENTS_UNAVAILABLE` - `gpgs.ERROR_STATUS_SNAPSHOT_CREATION_FAILED` - `gpgs.ERROR_STATUS_SNAPSHOT_FOLDER_UNAVAILABLE` - `gpgs.ERROR_STATUS_SNAPSHOT_NOT_FOUND` Or it can be ApiException.getStatusCode() (if ApiException was thrown) - `metadata` (table) - Metadata of the loaded save. Available only if `message_id` is `gpgs.MSG_LOAD_SNAPSHOT`. - `conflictId` (string) - The conflict id. Available only if `status` is `gpgs.STATUS_CONFLICT`. - `conflictMetadata` (table) - The conflicting metadata. Available only if `status` is `gpgs.STATUS_CONFLICT`. **Examples** ``` function callback(self, message_id, message) if message_id == gpgs.MSG_SIGN_IN or message_id == gpgs.MSG_SILENT_SIGN_IN then if message.status == gpgs.STATUS_SUCCESS then -- do something after login end elseif message_id == gpgs.MSG_LOAD_SNAPSHOT then -- do something when a save was loaded end end function init(self) gpgs.set_callback(callback) end function init(self) gpgs.set_callback(nil) -- remove callback end ``` ### gpgs.snapshot_display_saves *Type:* FUNCTION Provides a default saved games selection user interface. **Parameters** - `popupTitle` (string) - The title to display in the action bar. By default "Game Saves". - `allowAddButton` (boolean) - Whether or not to display a "create new snapshot" option in the selection UI. By default `true`. - `allowDelete` (boolean) - Whether or not to provide a delete overflow menu option for each snapshot in the selection UI. By default `true`. - `maxNumberOfSavedGamesToShow` (number) - The maximum number of snapshots to display in the UI. By default 5. **Examples** ``` if gpgs then gpgs.snapshot_display_saves("Choose the save of the game", false, true, 10) end ``` ### gpgs.snapshot_open *Type:* FUNCTION Opens a snapshot with the given `saveName`. If `createIfNotFound` is set to `true`, the specified snapshot will be created if it does not already exist. **Parameters** - `saveName` (string) - The name of the snapshot file to open. Must be between 1 and 100 non-URL-reserved characters (a-z, A-Z, 0-9, or the symbols "-", ".", "_", or "~"). - `createIfNotFound` (boolean) - If `true`, the snapshot will be created if one cannot be found. - `conflictPolicy` (number) - The conflict resolution policy to use for this snapshot that can be one of the predefined constants below - `gpgs.RESOLUTION_POLICY_MANUAL` - `gpgs.RESOLUTION_POLICY_LONGEST_PLAYTIME` - `gpgs.RESOLUTION_POLICY_LAST_KNOWN_GOOD` - `gpgs.RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED` - `gpgs.RESOLUTION_POLICY_HIGHEST_PROGRESS` Default value is `gpgs.RESOLUTION_POLICY_LAST_KNOWN_GOOD` **Examples** ``` if gpgs then gpgs.snapshot_open("my_save_1", true, gpgs.RESOLUTION_POLICY_LONGEST_PLAYTIME) end ``` ### gpgs.snapshot_commit_and_close *Type:* FUNCTION Save the currently opened save on the server and close it. **Parameters** - `metadata` (table) - A table with metadata for a save. It contains the fields below - `playedTime` (number) - The new played time to set for the snapshot in ms. - `progressValue` (number) - The new progress value to set for the snapshot. - `description` (string) - The new description to set for the snapshot. - `coverImage` (object) - The new cover image to set for the snapshot in `png`. **Examples** ``` if gpgs then local png_img, w, h = screenshot.png() gpgs.snapshot_commit_and_close({ coverImage = png_img, description = "LEVEL 31, CAVE", playedTime = 12345667, progressValue = 657 }) end ``` ### gpgs.snapshot_get_data *Type:* FUNCTION Returns the currently opened snapshot data. **Returns** - `string` - The byte array data of the currently opened snapshot. `nil` if something goes wrong. - `string` - An error message if something goes wrong. **Examples** ``` if gpgs then local bytes, error_message = gpgs.snapshot_get_data() if not bytes then print("snapshot_get_data ERROR:", error_message) else print("snapshot_get_data",bytes) -- Do something with your data end end ``` ### gpgs.snapshot_set_data *Type:* FUNCTION Sets the data for the currently opened snapshot. **Parameters** - `data` (string) - The data to set. **Returns** - `boolean` - True if data was set for the currently opened snapshot. - `string` - An error message if something goes wrong. **Examples** ``` if gpgs then local success, error_message = gpgs.snapshot_set_data(my_data) if not success then print("snapshot_set_data ERROR:", error_message) end end ``` ### gpgs.snapshot_is_opened *Type:* FUNCTION Check if a snapshot was opened. **Returns** - `boolean` - A current snapshot state. **Examples** ``` if gpgs then local is_opened = gpgs.snapshot_is_opened() end ``` ### gpgs.snapshot_get_max_image_size *Type:* FUNCTION Returns the maximum data size per snapshot cover image in bytes. **Returns** - `number` - The maximum data size per snapshot cover image in bytes. **Examples** ``` if gpgs then local image_size = gpgs.snapshot_get_max_image_size() end ``` ### gpgs.snapshot_get_max_save_size *Type:* FUNCTION Returns the maximum data size per snapshot in bytes. **Returns** - `number` - The maximum data size per snapshot in bytes. **Examples** ``` if gpgs then local data_size = gpgs.snapshot_get_max_save_size() end ``` ### gpgs.snapshot_get_conflicting_data *Type:* FUNCTION Returns the conflicting snapshot data. **Returns** - `string` - The byte array data of the conflicting snapshot. `nil` if something goes wrong. - `boolean` - An error message if something goes wrong. **Examples** ``` if gpgs then local bytes, error_message = gpgs.snapshot_get_conflicting_data() if not bytes then print("snapshot_get_conflicting_data ERROR:", error_message) else print("snapshot_get_conflicting_data:",bytes) -- Do something with conflicting data data end end ``` ### gpgs.snapshot_resolve_conflict *Type:* FUNCTION Resolves a conflict using the data from the provided snapshot. **Parameters** - `conflictId` (string) - The conflict id that you want to resolve. Provided in `message` table with `STATUS_CONFLICT` message type. - `snapshotId` (number) - Type of the snapshot you want to use for conflict solving that can be one of the predefined constants below - `gpgs.SNAPSHOT_CURRENT` - `gpgs.SNAPSHOT_CONFLICTING` **Examples** ``` if gpgs then gpgs.snapshot_resolve_conflict(self.conflictId, gpgs.SNAPSHOT_CONFLICTING) end ``` ### gpgs.leaderboard_submit_score *Type:* FUNCTION Submit a score to a leaderboard for the currently signed-in player. **Parameters** - `leaderboardId` (string) - `score` (number) ### gpgs.leaderboard_get_top_scores *Type:* FUNCTION Asynchronously gets the top page of scores for a leaderboard. **Parameters** - `leaderboardId` (string) - `time_span` (number) - One of the gpgs.TIME_SPAN_ constants - `collection` (number) - One of the gpgs.COLLECTION_ constants - `max_results` (number) - Between 1-25 ### gpgs.leaderboard_get_player_centered_scores *Type:* FUNCTION Asynchronously gets a player-centered page of scores for a leaderboard. **Parameters** - `leaderboardId` (string) - `time_span` (number) - One of the gpgs.TIME_SPAN_ constants - `collection` (number) - One of the gpgs.COLLECTION_ constants - `max_results` (number) - Between 1-25 - `force_reload` (boolean) - If true, this call will clear any locally cached data and attempt to fetch the latest data from the server ### gpgs.leaderboard_show *Type:* FUNCTION Show a leaderboard for a game specified by a leaderboardId. **Parameters** - `leaderboardId` (string) - `time_span` (number) - One of the gpgs.TIME_SPAN_ constants - `collection` (number) - One of the gpgs.COLLECTION_ constants ### gpgs.leaderboard_list *Type:* FUNCTION Show the list of leaderboards. ### gpgs.leaderboard_get_player_score *Type:* FUNCTION Asynchronously gets a player-centered page of scores for a leaderboard. **Parameters** - `leaderboardId` (string) - `time_span` (number) - One of the gpgs.TIME_SPAN_ constants - `collection` (number) - One of the gpgs.COLLECTION_ constants ### gpgs.achievement_reveal *Type:* FUNCTION Reveals a hidden achievement to the current player. **Parameters** - `achievementId` (string) - Achievement id (from GP console) ### gpgs.achievement_unlock *Type:* FUNCTION Unlocks an achievement for the current player. **Parameters** - `achievementId` (string) - Achievement id (from GP console) ### gpgs.achievement_set *Type:* FUNCTION Sets an achievement to have at least the given number of steps completed. **Parameters** - `achievementId` (string) - Achievement id (from GP console) - `steps` (number) - The number of steps to set the achievement to. Must be greater than 0. ### gpgs.achievement_increment *Type:* FUNCTION Increments an achievement by the given number of steps. **Parameters** - `achievementId` (string) - Achievement id (from GP console) - `steps` (number) - The number of steps to increment by. Must be greater than 0. ### gpgs.achievement_show *Type:* FUNCTION Show achivements ### gpgs.achievement_get *Type:* FUNCTION Get information about all achievement's state asynchronously. Result return to callback previously set by `gpgs.set_callback` with `message_id == gpgs.MSG_ACHIEVEMENTS`. Result is array of tables which contain following fields - `id` - achievement id (from GP console) - `name` - achievement name - `description` - achievement description - `xp` - how much experience points will be added when achievement will be unlocked - `steps` - current step of incremental achievement - `total_steps` - total amount of steps of incremental achievement - `unlocked` - set to `true` if achievement is unlocked. Otherwise field is missed. - `hidden` - set to `true if achievement is hidden. Otherwise field is missed. - `revealed` - set to `true` if achievement is revealed. Otherwise field is missed. ### gpgs.event_increment *Type:* FUNCTION Increments an event specified by `eventId` by the given number of steps **Parameters** - `eventId` (string) - Event id (from GP console) - `amount` (number) - The amount increment by. Must be greater than or equal to 0 ### gpgs.event_get *Type:* FUNCTION Get information about all events asynchronously. Result returns to callback previously set by `gpgs.set_callback` with `message_id == gpgs.MSG_GET_EVENTS`. Result is array of tables which contain following fields - `id` - event id - `formatted_value` - sum of all increments have been made to this event - `value` - the number of increments this user has made to this event - `description` - event's description - `image` - URI that can be used to load the event's image icon - `name` - event's name - `visible` - whether the event should be displayed to the user in any event related UIs ### RESOLUTION_POLICY_MANUAL *Type:* VARIABLE Official [GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/SnapshotsClient.html#RESOLUTION_POLICY_MANUAL) for this constant ### RESOLUTION_POLICY_LONGEST_PLAYTIME *Type:* VARIABLE Official [GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/SnapshotsClient.html#RESOLUTION_POLICY_LONGEST_PLAYTIME) for this constant ### RESOLUTION_POLICY_LAST_KNOWN_GOOD *Type:* VARIABLE Official [GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/SnapshotsClient.html#RESOLUTION_POLICY_LAST_KNOWN_GOOD) for this constant ### RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED *Type:* VARIABLE Official [GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/SnapshotsClient.html#RESOLUTION_POLICY_MOST_RECENTLY_MODIFIED) for this constant ### RESOLUTION_POLICY_HIGHEST_PROGRESS *Type:* VARIABLE Official [GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/SnapshotsClient.html#RESOLUTION_POLICY_HIGHEST_PROGRESS) for this constant ### MSG_SIGN_IN *Type:* VARIABLE The message type that GPGS sends when finishing the asynchronous operation after calling `gpgs.login()` ### MSG_SILENT_SIGN_IN *Type:* VARIABLE The message type that GPGS sends when finishing the asynchronous operation after calling `gpgs.silent_login()` ### MSG_SHOW_SNAPSHOTS *Type:* VARIABLE The message type that GPGS sends when finishing the asynchronous operation after calling `gpgs.snapshot_display_saves()` ### MSG_LOAD_SNAPSHOT *Type:* VARIABLE The message type that GPGS sends when finishing the asynchronous operation after calling `gpgs.snapshot_open()` ### MSG_SAVE_SNAPSHOT *Type:* VARIABLE The message type that GPGS sends when finishing the asynchronous operation after calling `gpgs.snapshot_commit_and_close()` ### MSG_GET_SERVER_TOKEN *Type:* VARIABLE The message type that GPGS sends when finishing the asynchronous operation of server token retrieval ### STATUS_SUCCESS *Type:* VARIABLE An operation success. ### STATUS_FAILED *Type:* VARIABLE An operation failed. Check the error field in the massage table. ### STATUS_CREATE_NEW_SAVE *Type:* VARIABLE A user wants to create new save as a result of `gpgs.snapshot_display_saves()` method. Turn off this button in `gpgs.snapshot_display_saves()` if you don't want to have this functionality. ### STATUS_CONFLICT *Type:* VARIABLE The result of the calling `gpgs.snapshot_open()` or 'gpgs.snapshot_resolve_conflict()' is a conflict. You need to make decision on how to solve this conflict using 'gpgs.snapshot_resolve_conflict()'. ### SNAPSHOT_CURRENT *Type:* VARIABLE The second parameter for 'gpgs.snapshot_resolve_conflict()' method, which means that you want to choose the current snapshot as a snapshot for conflict solving. ### SNAPSHOT_CONFLICTING *Type:* VARIABLE The second parameter for 'gpgs.snapshot_resolve_conflict()' method, which means that you want to choose the conflicting snapshot as a snapshot for conflict solving. ### ERROR_STATUS_SNAPSHOT_NOT_FOUND *Type:* VARIABLE This constant is used in `message.error_status` table when `MSG_LOAD_SNAPSHOT` is `STATUS_FAILED`. [Official GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/GamesStatusCodes.html#STATUS_SNAPSHOT_NOT_FOUND) for this constant ### ERROR_STATUS_SNAPSHOT_CREATION_FAILED *Type:* VARIABLE This constant is used in `message.error_status` table when `MSG_LOAD_SNAPSHOT` is `STATUS_FAILED`. [Official GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/GamesStatusCodes.html#STATUS_SNAPSHOT_CREATION_FAILED) for this constant ### ERROR_STATUS_SNAPSHOT_CONTENTS_UNAVAILABLE *Type:* VARIABLE This constant is used in `message.error_status` table when `MSG_LOAD_SNAPSHOT` is `STATUS_FAILED`. [Official GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/GamesStatusCodes.html#STATUS_SNAPSHOT_CONTENTS_UNAVAILABLE) for this constant ### ERROR_STATUS_SNAPSHOT_COMMIT_FAILED *Type:* VARIABLE This constant is used in `message.error_status` table when `MSG_LOAD_SNAPSHOT` is `STATUS_FAILED`. [Official GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/GamesStatusCodes.html#STATUS_SNAPSHOT_COMMIT_FAILED) for this constant ### ERROR_STATUS_SNAPSHOT_FOLDER_UNAVAILABLE *Type:* VARIABLE This constant is used in `message.error_status` table when `MSG_LOAD_SNAPSHOT` is `STATUS_FAILED`. [Official GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/GamesStatusCodes.html#STATUS_SNAPSHOT_FOLDER_UNAVAILABLE) for this constant ### ERROR_STATUS_SNAPSHOT_CONFLICT_MISSING *Type:* VARIABLE This constant is used in `message.error_status` table when `MSG_LOAD_SNAPSHOT` is `STATUS_FAILED`. [Official GPGS documentation](https://developers.google.com/android/reference/com/google/android/gms/games/GamesStatusCodes.html#STATUS_SNAPSHOT_CONFLICT_MISSING) for this constant # extension-iac {#apis:extension-iac_iac} **Namespace:** `iac` **Language:** Lua **Type:** Extension Functions and constants for doing inter-app communication. Supported on iOS and Android. [icon:ios] [icon:android] ## API ### iac.set_listener *Type:* FUNCTION Sets the listener function for inter-app communication events. **Parameters** - `self` (object) - The current object. - `payload` (table) - The iac payload. - `type` (number) - The type of iac, an iac.TYPE_ enumeration. It can be one of the predefined constants below - `iac.TYPE_INVOCATION` **Examples** ``` local function iac_listener(self, payload, type) if type == iac.TYPE_INVOCATION then -- This was an invocation print(payload.origin) -- origin may be empty string if it could not be resolved print(payload.url) end end function init(self) iac.set_listener(iac_listener) end ``` ### TYPE_INVOCATION *Type:* VARIABLE iac type # extension-iap {#apis:extension-iap_iap} **Namespace:** `iap` **Language:** Lua **Type:** Extension Functions and constants for doing in-app purchases. Supported on iOS, Android (Google Play and Amazon) and Facebook Canvas platforms. [icon:ios] [icon:googleplay] [icon:amazon] [icon:facebook] ## API ### iap.buy *Type:* FUNCTION Purchase a product. **Parameters** - `id` (string) - product to buy - `options` (table) - optional parameters as properties. The following parameters can be set - `request_id` (string) - Facebook only [icon:facebook]. Optional custom unique request id to set for this transaction. The id becomes attached to the payment within the Graph API. - `token` (string) - Google Play only [icon:googleplay]. Which subscription offer to use when buying a subscription. The token can be retrieved from the subscriptions table returned when calling iap.list() **Examples** ``` local function iap_listener(self, transaction, error) if error == nil then -- purchase is successful. print(transaction.date) -- required if auto finish transactions is disabled in project settings if (transaction.state == iap.TRANS_STATE_PURCHASED) then -- do server-side verification of purchase here.. iap.finish(transaction) end else print(error.error, error.reason) end end function init(self) iap.set_listener(iap_listener) iap.buy("my_iap") end ``` ### iap.finish *Type:* FUNCTION Explicitly finish a product transaction. [icon:attention] Calling iap.finish is required on a successful transaction if `auto_finish_transactions` is disabled in project settings. Calling this function with `auto_finish_transactions` set will be ignored and a warning is printed. The `transaction.state` field must equal `iap.TRANS_STATE_PURCHASED`. **Parameters** - `transaction` (table) - transaction table parameter as supplied in listener callback ### iap.acknowledge *Type:* FUNCTION Acknowledge a transaction. [icon:attention] Calling iap.acknowledge is required on a successful transaction on Google Play unless iap.finish is called. The transaction.state field must equal iap.TRANS_STATE_PURCHASED. **Parameters** - `transaction` (table) - transaction table parameter as supplied in listener callback ### iap.get_provider_id *Type:* FUNCTION Get current iap provider **Returns** - `constant` - one of the following values - `iap.PROVIDER_ID_GOOGLE` - `iap.PROVIDER_ID_AMAZON` - `iap.PROVIDER_ID_APPLE` - `iap.PROVIDER_ID_FACEBOOK` ### iap.list *Type:* FUNCTION Get a list of all avaliable iap products. **Parameters** - `ids` (table) - table (array) of identifiers to get products from - `callback` (function) - result callback taking the following parameters - `self` (object) - The current object. - `products` (table) - a table describing the available iap products. - `ident` (string) - The product identifier. - `title` (string) - The product title. - `description` (string) - The product description. - `price` (number) - The price of the product. For Google Play [icon:googleplay] this is used only for in-app products - `price_string` (string) - The price of the product, as a formatted string (amount and currency symbol). For Google Play [icon:googleplay] this is used only for in-app products - `currency_code` (string) - The currency code. For Google Play [icon:googleplay] this is the merchant's locale, instead of the user's. For Google Play [icon:googleplay] this is used only for in-app products - `onetime` (table) - Only available for Google Play [icon:googleplay]. List of one-time purchase offers. - `token` (string) - The token associated with the offer. - `price` (number) - The price of the product. - `price_string` (string) - The price of the product, as a formatted string (amount and currency symbol). - `currency_code` (string) - The currency code. - `subscriptions` (table) - Only available for Google Play [icon:googleplay]. List of subscription offers. Each offer contains a token and a list of price and billing options. See https://developer.android.com/reference/com/android/billingclient/api/ProductDetails.PricingPhase - `token` (string) - The token associated with the pricing phases for the subscription. - `pricing` (table) - The pricing phases for the subscription. - `price_string` (string) - Formatted price for the payment cycle, including currency sign. - `price` (number) - Price of the payment cycle in micro-units. - `currency_code` (string) - ISO 4217 currency code - `billing_period` (string) - Billing period of the payment cycle, specified in ISO 8601 format - `billing_cycle_count` (number) - Number of cycles for which the billing period is applied. - `recurrence_mode` (string) - FINITE, INFINITE or NONE - `error` (table) - a table containing error information. `nil` if there is no error. - `error` (the error message) **Examples** ``` local function iap_callback(self, products, error) if error == nil then for k,p in pairs(products) do -- present the product print(p.title) print(p.description) end else print(error.error) end end function init(self) iap.list({"my_iap"}, iap_callback) end ``` ### iap.restore *Type:* FUNCTION Restore previously purchased products. **Returns** - `boolean` - value is `true` if current store supports handling restored transactions, otherwise `false`. ### iap.set_listener *Type:* FUNCTION Set the callback function to receive purchase transaction events. **Parameters** - `listener` (function) - listener callback function. Pass an empty function if you no longer wish to receive callbacks. - `self` (object) - The current object. - `transaction` (table) - a table describing the transaction. - `ident` (string) - The product identifier. - `state` (string) - The transaction state. One of the following - `iap.TRANS_STATE_FAILED` - `iap.TRANS_STATE_PURCHASED` - `iap.TRANS_STATE_PURCHASING` - `iap.TRANS_STATE_RESTORED` - `iap.TRANS_STATE_UNVERIFIED` - `date` (string) - The date and time for the transaction. - `trans_ident` (string) - The transaction identifier. This field is only set when `state` is `TRANS_STATE_RESTORED`, `TRANS_STATE_UNVERIFIED` or `TRANS_STATE_PURCHASED`. - `receipt` (string) - The transaction receipt. This field is only set when `state` is `TRANS_STATE_PURCHASED` or `TRANS_STATE_UNVERIFIED`. - `original_trans` (string) - Apple only [icon:apple]. The original transaction. This field is only set when `state` is `TRANS_STATE_RESTORED`. - `original_json` (string) - Android only [icon:android]. The purchase order details in JSON format. - `signature` (string) - Google Play only [icon:googleplay]. A string containing the signature of the purchase data that was signed with the private key of the developer. - `request_id` (string) - Facebook only [icon:facebook]. This field is set to the optional custom unique request id `request_id` if set in the `iap.buy()` call parameters. - `user_id` (string) - Amazon Pay only [icon:amazon]. The user ID. - `is_sandbox_mode` (boolean) - Amazon Pay only [icon:amazon]. If `true`, the SDK is running in Sandbox mode. This only allows interactions with the Amazon AppTester. Use this mode only for testing locally. - `cancel_date` (string) - Amazon Pay only [icon:amazon]. The cancel date for the purchase. This field is only set if the purchase is canceled. - `canceled` (string) - Amazon Pay only [icon:amazon]. Is set to `true` if the receipt was canceled or has expired; otherwise `false`. - `error` (table) - a table containing error information. `nil` if there is no error. `error` - the error message. `reason` - the reason for the error, value can be one of the following constants - `iap.REASON_UNSPECIFIED` - `iap.REASON_USER_CANCELED` - `iap.REASON_ITEM_ALREADY_OWNED` ### PROVIDER_ID_AMAZON *Type:* VARIABLE provider id for Amazon ### PROVIDER_ID_APPLE *Type:* VARIABLE provider id for Apple ### PROVIDER_ID_FACEBOOK *Type:* VARIABLE provider id for Facebook ### PROVIDER_ID_GOOGLE *Type:* VARIABLE iap provider id for Google ### REASON_UNSPECIFIED *Type:* VARIABLE unspecified error reason ### REASON_USER_CANCELED *Type:* VARIABLE user canceled reason ### REASON_ITEM_ALREADY_OWNED *Type:* VARIABLE the item is already owned by the user ### TRANS_STATE_FAILED *Type:* VARIABLE transaction failed state ### TRANS_STATE_PURCHASED *Type:* VARIABLE transaction purchased state ### TRANS_STATE_PURCHASING *Type:* VARIABLE transaction purchasing state This is an intermediate mode followed by TRANS_STATE_PURCHASED. Store provider support dependent. ### TRANS_STATE_RESTORED *Type:* VARIABLE transaction restored state This is only available on store providers supporting restoring purchases. ### TRANS_STATE_UNVERIFIED *Type:* VARIABLE transaction unverified state, requires verification of purchase # extension-ironsource {#apis:extension-ironsource_ironsource} **Namespace:** `ironsource` **Language:** Lua **Type:** Extension Functions and constants for interacting with IronSource API ## API ### ironsource.init *Type:* FUNCTION Initialize the IronSource SDK **Parameters** - `app_key` (string) - App key you can get in the IronSource dashboard ### ironsource.set_callback *Type:* FUNCTION Sets a callback function for receiving events from the SDK. Call `ironsource.set_callback(nil)` to remove callback **Parameters** - `callback` (function) - Callback function that is executed on any event in the SDK. - `self` (object) - The calling script instance - `message_id` (number) - One of message types: `ironsource.MSG_INIT` initialization, `ironsource.MSG_INTERSTITIAL` message from Interstitial ad unit, `ironsource.MSG_REWARDED` message from Rewarded ad unit - `message` (table) - A table holding the data. It always contains `event`, and also some other values depends on a message - `event` (number) - One of event types: `ironsource.EVENT_AD_AVAILABLE`, `ironsource.EVENT_AD_UNAVAILABLE`, `ironsource.EVENT_AD_OPENED`, `ironsource.EVENT_AD_CLOSED`, `ironsource.EVENT_AD_REWARDED`, `ironsource.EVENT_AD_CLICKED`, `ironsource.EVENT_AD_SHOW_FAILED`, `ironsource.EVENT_AD_READY`, `ironsource.EVENT_AD_SHOW_SUCCEEDED`, `ironsource.EVENT_AD_LOAD_FAILED` `ironsource.EVENT_JSON_ERROR` `ironsource.EVENT_INIT_COMPLETE` `ironsource.EVENT_CONSENT_LOADED` `ironsource.EVENT_CONSENT_SHOWN` `ironsource.EVENT_CONSENT_LOAD_FAILED` `ironsource.EVENT_CONSENT_SHOW_FAILED` `ironsource.EVENT_CONSENT_ACCEPTED` `ironsource.EVENT_CONSENT_DISMISSED` `ironsource.EVENT_STATUS_AUTHORIZED` `ironsource.EVENT_STATUS_DENIED` `ironsource.EVENT_STATUS_NOT_DETERMINED` `ironsource.EVENT_STATUS_RESTRICTED` **Examples** ``` local function ironsource_callback(self, message_id, message) callback_logger(self, message_id, message) if message_id == ironsource.MSG_INIT then if message.event == ironsource.EVENT_INIT_COMPLETE then -- ironSource SDK is initialized -- massage{} end elseif message_id == ironsource.MSG_REWARDED then if message.event == ironsource.EVENT_AD_AVAILABLE then -- Indicates that there's an available ad. -- The adInfo object includes information about the ad that was loaded successfully -- massage{AdInfo} elseif message.event == ironsource.EVENT_AD_UNAVAILABLE then -- Indicates that no ads are available to be displayed -- massage{} elseif message.event == ironsource.EVENT_AD_OPENED then -- The Rewarded Video ad view has opened. Your activity will loose focus -- massage{AdInfo} elseif message.event == ironsource.EVENT_AD_CLOSED then -- The Rewarded Video ad view is about to be closed. Your activity will regain its focus -- massage{AdInfo} elseif message.event == ironsource.EVENT_AD_REWARDED then -- The user completed to watch the video, and should be rewarded. -- The placement parameter will include the reward data. -- When using server-to-server callbacks, you may ignore this event and wait for the ironSource server callback -- massage{AdInfo, Placement} elseif message.event == ironsource.EVENT_AD_SHOW_FAILED then -- The rewarded video ad was failed to show -- massage{AdInfo, IronSourceError} elseif message.event == ironsource.EVENT_AD_CLICKED then -- Invoked when the video ad was clicked. -- This callback is not supported by all networks, and we recommend using it -- only if it's supported by all networks you included in your build -- massage{AdInfo, Placement} end elseif message_id == ironsource.MSG_INTERSTITIAL then if message.event == ironsource.EVENT_AD_READY then -- Invoked when the interstitial ad was loaded successfully. -- AdInfo parameter includes information about the loaded ad -- massage{AdInfo} elseif message.event == ironsource.EVENT_AD_LOAD_FAILED then -- Indicates that the ad failed to be loaded -- massage{IronSourceError} elseif message.event == ironsource.EVENT_AD_OPENED then -- Invoked when the Interstitial Ad Unit has opened, and user left the application screen. -- This is the impression indication. -- massage{AdInfo} elseif message.event == ironsource.EVENT_AD_CLOSED then -- Invoked when the interstitial ad closed and the user went back to the application screen. -- massage{AdInfo} elseif message.event == ironsource.EVENT_AD_SHOW_FAILED then -- Invoked when the ad failed to show -- massage{AdInfo, IronSourceError} elseif message.event == ironsource.EVENT_AD_CLICKED then -- Invoked when end user clicked on the interstitial ad -- massage{AdInfo} elseif message.event == ironsource.EVENT_AD_SHOW_SUCCEEDED then -- Invoked before the interstitial ad was opened, and before the InterstitialOnAdOpenedEvent is reported. -- This callback is not supported by all networks, and we recommend using it only if -- it's supported by all networks you included in your build. -- massage{AdInfo} end elseif message_id == ironsource.MSG_CONSENT then if message.event == ironsource.EVENT_CONSENT_LOADED then -- Consent View was loaded successfully -- massage.consent_view_type elseif message.event == ironsource.EVENT_CONSENT_SHOWN then -- Consent view was displayed successfully -- massage.consent_view_type elseif message.event == ironsource.EVENT_CONSENT_LOAD_FAILED then -- Consent view was failed to load -- massage.consent_view_type, massage.error_code, massage.error_message elseif message.event == ironsource.EVENT_CONSENT_SHOW_FAILED then -- Consent view was not displayed, due to error -- massage.consent_view_type, massage.error_code, massage.error_message elseif message.event == ironsource.EVENT_CONSENT_ACCEPTED then -- The user pressed the Settings or Next buttons -- massage.consent_view_type elseif message.event == ironsource.EVENT_CONSENT_DISMISSED then -- The user dismiss consent -- massage.consent_view_type end elseif message_id == ironsource.MSG_IDFA then if message.event == ironsource.EVENT_STATUS_AUTHORIZED then -- ATTrackingManagerAuthorizationStatusAuthorized elseif message.event == ironsource.EVENT_STATUS_DENIED then -- ATTrackingManagerAuthorizationStatusDenied elseif message.event == ironsource.EVENT_STATUS_NOT_DETERMINED then -- ATTrackingManagerAuthorizationStatusNotDetermined elseif message.event == ironsource.EVENT_STATUS_RESTRICTED then -- ATTrackingManagerAuthorizationStatusRestricted end end end ``` ### ironsource.set_consent *Type:* FUNCTION If the user provided consent, set the following flag to true (must be called before `ironsource.init()`). [Original docs](https://developers.is.com/ironsource-mobile/general/making-sure-youre-compliant-post-gdpr/#step-2) [Android](https://developers.is.com/ironsource-mobile/android/regulation-advanced-settings/), [iOS](https://developers.is.com/ironsource-mobile/ios/regulation-advanced-settings/) **Parameters** - `is_consent_provided` (boolean) ### ironsource.validate_integration *Type:* FUNCTION The ironSource SDK provides an easy way to verify that you’ve successfully integrated the ironSource SDK and any additional adapters; it also makes sure all required dependencies and frameworks were added for the various mediated ad networks. The Integration Helper will now also portray the compatibility between the SDK and adapter versions. Original docs [Android](https://developers.is.com/ironsource-mobile-android/integration-helper-android/), [iOS](https://developers.is.com/ironsource-mobile/ios/integration-helper-ios/) ### ironsource.set_metadata *Type:* FUNCTION Function used for setting different parameterd for adapters and the SDK itself. **Parameters** - `key` (String) - `value` (String) ### ironsource.set_user_id *Type:* FUNCTION If you’re serving the offerwall ad unit or using server-to-server callbacks to reward your users with ironSource SDK rewarded ad units, you must define a unique identifier for each user (“UserID”), using the setUserID method. Set the UserID before the init request, to make sure you avoid any data loses, related to the user. Use a unique identifier, with up to 64 alphanumeric characters. Original docs [Android](https://developers.is.com/ironsource-mobile/android/advanced-settings/), [iOS](https://developers.is.com/ironsource-mobile/ios/advanced-settings-2/) **Parameters** - `user_id` (string) ### ironsource.launch_test_suite *Type:* FUNCTION The LevelPlay integration test suite enables you to quickly and easily test your app’s integration, verify platform setup and review ads related to your configured networks. Original docs [Android](https://developers.is.com/ironsource-mobile/android/unity-levelplay-test-suite/#step-1), [iOS](https://developers.is.com/ironsource-mobile/ios/unity-levelplay-test-suite/) ### ironsource.request_idfa *Type:* FUNCTION iOS Only. Display the App Tracking Transparency authorization request for accessing the IDFA. Original docs [iOS](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/3547037-requesttrackingauthorization) ### ironsource.get_idfa_status *Type:* FUNCTION iOS Only. Returns current authorization status for the IDFA One of event types: `ironsource.EVENT_STATUS_AUTHORIZED` `ironsource.EVENT_STATUS_DENIED` `ironsource.EVENT_STATUS_NOT_DETERMINED` `ironsource.EVENT_STATUS_RESTRICTED` or nil if not supported Original docs [iOS](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/3547037-requesttrackingauthorization) ### ironsource.set_adapters_debug *Type:* FUNCTION Manage the debug logs for your integrated mediation ad networks with this boolean. When set to TRUE it enables debug logs to help you troubleshoot issues with all of the mediation ad networks that permit to do so. Remove this code before your app goes live with our ad units! **Returns** - `boolean` ### ironsource.load_consent_view *Type:* FUNCTION iOS Only. Load the IronSource permission pop-up. [iOS](https://developers.is.com/ironsource-mobile/ios/permission-popup-ios/#step-1) **Returns** - `string` - one of the folowing values "pre" or "post" ### ironsource.show_consent_view *Type:* FUNCTION iOS Only. Display the IronSource permission pop-up. [iOS](https://developers.is.com/ironsource-mobile/ios/permission-popup-ios/#step-1) **Returns** - `string` - one of the folowing values "pre" or "post" ### ironsource.should_track_network_state *Type:* FUNCTION You can determine and monitor the internet connection on the user’s device through the ironSource Network Change Status function. This enables the SDK to change its availability according to network modifications, i.e. in the case of no network connection, the availability will turn to FALSE. The default of this function is false; if you’d like to listen to it for changes in connectivity, activate it in the SDK initialization [Android shouldTrackNetworkState](https://developers.is.com/ironsource-mobile/android/rewarded-video-integration-android/#step-1), [iOS shouldTrackReachability](https://developers.is.com/ironsource-mobile/ios/rewarded-video-integration-ios/#step-1) **Parameters** - `should_track` (boolean) ### ironsource.is_rewarded_video_available *Type:* FUNCTION You can receive the availability status of the AD Unit through the callback. Alternatively, ask for ad availability directly by calling this function. [Android](https://developers.is.com/ironsource-mobile/android/rewarded-video-integration-android/#step-1), [iOS](https://developers.is.com/ironsource-mobile/ios/rewarded-video-integration-ios/#step-1) **Returns** - `boolean` ### ironsource.show_rewarded_video *Type:* FUNCTION You can show a video ad to your users and define the exact Placement you want to show an ad. The Reward settings of this Placement will be pulled from the ironSource server. Original docs [Android](https://developers.is.com/ironsource-mobile/android/rewarded-video-integration-android/#step-1), [iOS](https://developers.is.com/ironsource-mobile/ios/rewarded-video-integration-ios/#step-1) **Parameters** - `placement_name` (String) - maybe nil - then default placement used ### ironsource.get_rewarded_video_placement_info *Type:* FUNCTION Get details about the specific Reward associated with each Ad Placement. Original docs [Android](https://developers.is.com/ironsource-mobile/android/rewarded-video-integration-android/#step-1), [iOS](https://developers.is.com/ironsource-mobile/ios/rewarded-video-integration-ios/#step-1) **Parameters** - `placement_name` (String) ### ironsource.get_rewarded_video_placement_info *Type:* FUNCTION Get details about the specific Reward associated with each Ad Placement. Original docs [Android](https://developers.is.com/ironsource-mobile/android/rewarded-video-integration-android/#step-1), [iOS](https://developers.is.com/ironsource-mobile/ios/rewarded-video-integration-ios/#step-1) **Parameters** - `placement_name` (String) **Returns** - `table` - contains the following fields `placement_id`, `placement_name`, `is_default`, `reward_name`, `reward_amount` ### ironsource.is_rewarded_video_placement_capped *Type:* FUNCTION To ensure you don’t show the traffic driver (Rewarded Video button) to prompt the user to watch an ad when the placement is capped, you must call the below method to verify if a specific placement has reached its ad limit. When requesting availability, you might receive a TRUE response but in the case your placement has reached its capping limit, the ad will not be served to the user. Original docs [Android isRewardedVideoPlacementCapped](https://developers.is.com/ironsource-mobile/android/rewarded-video-integration-android/#step-2), [iOS isRewardedVideoCappedForPlacement](https://developers.is.com/ironsource-mobile/ios/rewarded-video-integration-ios/#step-2) **Parameters** - `placement_name` (String) **Returns** - `boolean` ### ironsource.set_dynamic_user_id *Type:* FUNCTION The Dynamic UserID is a parameter to verify AdRewarded transactions and can be changed throughout the session. To receive this parameter through the server to server callbacks, it must be set before calling showRewardedVideo. You will receive a dynamicUserId parameter in the callback URL with the reward details. [Android](https://developers.is.com/ironsource-mobile/android/rewarded-video-integration-android/#step-2), [iOS](https://developers.is.com/ironsource-mobile/ios/rewarded-video-integration-ios/#step-2) **Parameters** - `dynamic_user_id` (String) ### ironsource.load_interstitial *Type:* FUNCTION We recommend requesting an Interstitial Ad a short while before you plan on showing it to your users as the loading process can take time. [Android](https://developers.is.com/ironsource-mobile/android/interstitial-mediation-integration-android/#step-2), [iOS](https://developers.is.com/ironsource-mobile/ios/interstitial-integration-ios/#step-2) ### ironsource.is_interstitial_ready *Type:* FUNCTION You can receive the availability status of the AD Unit through the callback. Alternatively, ask for ad availability directly by calling this function. [Android](https://developers.is.com/ironsource-mobile/android/interstitial-mediation-integration-android/#step-2), [iOS](https://developers.is.com/ironsource-mobile/ios/interstitial-integration-ios/#step-2) **Returns** - `boolean` ### ironsource.get_interstitial_placement_info *Type:* FUNCTION Android Only. Get details about the specific Ad Placement. Original docs [Android](https://developers.is.com/ironsource-mobile/android/interstitial-mediation-integration-android/#step-3), [iOS](https://developers.is.com/ironsource-mobile/ios/interstitial-integration-ios/#step-3) **Parameters** - `placement_name` (String) **Returns** - `table` - contains the following fields `placement_id`, `placement_name`, `is_default` ### ironsource.is_interstitial_placement_capped *Type:* FUNCTION In addition to LevelPlay‘s Ad Placements, you can now configure capping and pacing settings for selected placements. Capping and pacing improve the user experience in your app by limiting the number of ads served within a defined timeframe. Original docs [Android](https://developers.is.com/ironsource-mobile/android/interstitial-mediation-integration-android/#step-3), [iOS](https://developers.is.com/ironsource-mobile/ios/interstitial-integration-ios/#step-3) **Parameters** - `placement_name` (String) **Returns** - `boolean` ### ironsource.show_interstitial *Type:* FUNCTION Serve an Interstitial ad to your users. Call it once you receive the ironsource.EVENT_AD_READY callback, you are ready to show an Interstitial Ad to your users. To provide the best experience for your users, make sure to pause any game action, including audio, during the time the ad is displayed. Original docs [Android](https://developers.is.com/ironsource-mobile/android/rewarded-video-integration-android/#step-1), [iOS](https://developers.is.com/ironsource-mobile/ios/rewarded-video-integration-ios/#step-1) **Parameters** - `placement_name` (String) - maybe nil - then default placement used ### MSG_INTERSTITIAL *Type:* VARIABLE ### MSG_REWARDED *Type:* VARIABLE ### MSG_CONSENT *Type:* VARIABLE ### MSG_INIT *Type:* VARIABLE ### MSG_IDFA *Type:* VARIABLE ### EVENT_AD_AVAILABLE *Type:* VARIABLE ### EVENT_AD_UNAVAILABLE *Type:* VARIABLE ### EVENT_AD_OPENED *Type:* VARIABLE ### EVENT_AD_CLOSED *Type:* VARIABLE ### EVENT_AD_REWARDED *Type:* VARIABLE ### EVENT_AD_CLICKED *Type:* VARIABLE ### EVENT_AD_SHOW_FAILED *Type:* VARIABLE ### EVENT_AD_READY *Type:* VARIABLE ### EVENT_AD_SHOW_SUCCEEDED *Type:* VARIABLE ### EVENT_AD_LOAD_FAILED *Type:* VARIABLE ### EVENT_JSON_ERROR *Type:* VARIABLE ### EVENT_INIT_COMPLETE *Type:* VARIABLE ### EVENT_CONSENT_LOADED *Type:* VARIABLE ### EVENT_CONSENT_SHOWN *Type:* VARIABLE ### EVENT_CONSENT_LOAD_FAILED *Type:* VARIABLE ### EVENT_CONSENT_SHOW_FAILED *Type:* VARIABLE ### EVENT_CONSENT_ACCEPTED *Type:* VARIABLE ### EVENT_CONSENT_DISMISSED *Type:* VARIABLE ### EVENT_STATUS_AUTHORIZED *Type:* VARIABLE ### EVENT_STATUS_DENIED *Type:* VARIABLE ### EVENT_STATUS_NOT_DETERMINED *Type:* VARIABLE ### EVENT_STATUS_RESTRICTED *Type:* VARIABLE # extension-network-info {#apis:extension-network-info_networkinfo} **Namespace:** `networkinfo` **Language:** Lua **Type:** Extension Functions to get information about the network configuration of the device. ## API ### networkinfo.get_proxy_info *Type:* FUNCTION Get information about proxies for a specific url. **Parameters** - `url` (string) - The url to get proxy configurations for **Returns** - `table` - A list of proxies to try in order. Each proxy has three values type: direct (no proxy), http, socks host: proxy url port: proxy port number # extension-odin {#apis:extension-odin_odin} **Namespace:** `odin` **Language:** Lua **Type:** Extension Functions and constants for interacting with ODIN Voice ## API ### odin.init *Type:* FUNCTION Initialize ODIN Voice **Parameters** - `listener` (function) **Returns** - `boolean` ### odin.create_room *Type:* FUNCTION Create or join a room. **Parameters** - `room_id` (string) - Id of the room to join - `user_id` (string) - Id of the user - `access_key` (string) - The access key used when generating a token for room access. Will use odin.access_key if none is provided. **Returns** - `boolean` ### odin.close_room *Type:* FUNCTION Close/leave a previously created/joined room. **Returns** - `boolean` ### odin.send *Type:* FUNCTION Send a message to the current room. **Parameters** - `data` (string) - Data to send. - `target_peer_ids` (table) - Optional table with peers to send message to. Nil to send to all. - `msgid` (number) - Optional message id to identify message by. The id will be used in the response. **Returns** - `boolean` # extension-pad {#apis:extension-pad_pad} **Namespace:** `pad` **Language:** Lua **Type:** Extension Functionality to work with Play Asset Delivery and the AssetPackManager ## API ### pad.cancel *Type:* FUNCTION Requests to cancel the download of the specified asset packs. **Parameters** - `pack_name` (string) ### pad.fetch *Type:* FUNCTION Requests to download the specified asset pack. **Parameters** - `pack_name` (string) ### pad.remove_pack *Type:* FUNCTION Deletes the specified asset pack from the internal storage of the app. **Parameters** - `pack_name` (string) ### pad.get_pack_state *Type:* FUNCTION Requests download state and details for the specified asset pack. This is an asynchronous function and will send a `PACK_STATE_UPDATED` event once the new state is available. **Parameters** - `pack_name` (string) ### pad.get_pack_location *Type:* FUNCTION Returns the location of the specified asset pack on the device or an empty string if this pack is not downloaded. **Parameters** - `pack_name` (string) **Returns** - `strin` ### pad.get_pack_bytes_downloaded *Type:* FUNCTION Returns the total number of bytes already downloaded for the pack. Note that you must have called the `get_pack_state()` function first and wait for a `PACK_STATE_UPDATED` event before calling this function. **Parameters** - `pack_name` (string) **Returns** - `bytes_downloade` ### pad.get_pack_error_code *Type:* FUNCTION Returns the error code for the pack, if Play has failed to download the pack. Note that you must have called the `get_pack_state()` function first and wait for a `PACK_STATE_UPDATED` event before calling this function. **Parameters** - `pack_name` (string) **Returns** - `error_cod` ### pad.get_pack_status *Type:* FUNCTION Returns the download status of the pack. Note that you must have called the `get_pack_state()` function first and wait for a `PACK_STATE_UPDATED` event before calling this function. **Parameters** - `pack_name` (string) **Returns** - `statu` ### pad.get_pack_total_bytes_to_download *Type:* FUNCTION Returns the total size of the pack in bytes. Note that you must have called the `get_pack_state()` function first and wait for a `PACK_STATE_UPDATED` event before calling this function. **Parameters** - `pack_name` (string) **Returns** - `bytes_to_downloa` ### pad.get_pack_transfer_progress_percentage *Type:* FUNCTION Returns the percentage of the asset pack already transferred to the app. Note that you must have called the `get_pack_state()` function first and wait for a `PACK_STATE_UPDATED` event before calling this function. **Parameters** - `pack_name` (string) **Returns** - `numbe` ### pad.show_confirmation_dialog *Type:* FUNCTION Shows a dialog that asks the user for consent to download packs Shows a dialog that asks the user for consent to download packs that are currently in either the AssetPackStatus.REQUIRES_USER_CONFIRMATION state or the AssetPackStatus.WAITING_FOR_WIFI state. Will return result in event listener. **Parameters** - `pack_name` (string) ### pad.set_listener *Type:* FUNCTION Set listener to receive events **Parameters** - `listener` (function) - The function to call (self, event) ### EVENT_PACK_STATE_UPDATED *Type:* VARIABLE ### EVENT_PACK_STATE_ERROR *Type:* VARIABLE ### EVENT_REMOVE_PACK_COMPLETED *Type:* VARIABLE ### EVENT_REMOVE_PACK_CANCELED *Type:* VARIABLE ### EVENT_REMOVE_PACK_ERROR *Type:* VARIABLE ### EVENT_DIALOG_CONFIRMED *Type:* VARIABLE ### EVENT_DIALOG_DECLINED *Type:* VARIABLE ### EVENT_DIALOG_CANCELED *Type:* VARIABLE ### EVENT_DIALOG_ERROR *Type:* VARIABLE ### STATUS_UNKNOWN *Type:* VARIABLE ### STATUS_PENDING *Type:* VARIABLE ### STATUS_DOWNLOADING *Type:* VARIABLE ### STATUS_TRANSFERRING *Type:* VARIABLE ### STATUS_COMPLETED *Type:* VARIABLE ### STATUS_FAILED *Type:* VARIABLE ### STATUS_CANCELED *Type:* VARIABLE ### STATUS_WAITING_FOR_WIFI *Type:* VARIABLE ### STATUS_NOT_INSTALLED *Type:* VARIABLE ### STATUS_REQUIRES_USER_CONFIRMATION *Type:* VARIABLE ### ERRORCODE_ACCESS_DENIED *Type:* VARIABLE Download not permitted under the current device circumstances ### ERRORCODE_API_NOT_AVAILABLE *Type:* VARIABLE The Asset Delivery API isn't available. ### ERRORCODE_APP_NOT_OWNED *Type:* VARIABLE The app isn't owned by any user on this device. ### ERRORCODE_APP_UNAVAILABLE *Type:* VARIABLE The requesting app is unavailable. ### ERRORCODE_CONFIRMATION_NOT_REQUIRED *Type:* VARIABLE Returned if AssetPackManager.showConfirmationDialog(Activity) is called but no asset packs require user confirmation. ### ERRORCODE_DOWNLOAD_NOT_FOUND *Type:* VARIABLE The requested download isn't found. ### ERRORCODE_INSUFFICIENT_STORAGE *Type:* VARIABLE Asset pack download failed due to insufficient storage. ### ERRORCODE_INTERNAL_ERROR *Type:* VARIABLE Unknown error downloading an asset pack. ### ERRORCODE_INVALID_REQUEST *Type:* VARIABLE The request is invalid. ### ERRORCODE_NETWORK_ERROR *Type:* VARIABLE Network error. ### ERRORCODE_NETWORK_UNRESTRICTED *Type:* VARIABLE Returned if AssetPackManager.showCellularDataConfirmation(Activity) is called but no asset packs are waiting for Wi-Fi. ### ERRORCODE_NO_ERROR *Type:* VARIABLE ### ERRORCODE_PACK_UNAVAILABLE *Type:* VARIABLE The requested asset pack isn't available. ### ERRORCODE_PLAY_STORE_NOT_FOUND *Type:* VARIABLE The Play Store app is either not installed or not the official version. ### ERRORCODE_UNRECOGNIZED_INSTALLATION *Type:* VARIABLE The installed app version is not recognized by Play. # extension-permissions {#apis:extension-permissions_permissions} **Namespace:** `permissions` **Language:** Lua **Type:** Extension Functions and constants for interacting with permissions related APIs ## API ### permissions.check *Type:* FUNCTION Determine whether you have been granted a particular permission. **Parameters** - `permission` (string) - A constant that represent permission, for example `android.permission.ACCESS_NETWORK_STATE` **Returns** - `number` - A result can be one of the predefined constants below - `permissions.PERMISSION_GRANTED` - `permissions.PERMISSION_DENIED` - `permissions.PERMISSION_SHOW_RATIONALE` **Examples** ``` local result = permissions.check("android.permission.ACCESS_NETWORK_STATE") if result == permissions.PERMISSION_DENIED then -- You can directly ask for the permission. elseif result == permissions.PERMISSION_GRANTED then -- You can use the API that requires the permission. elseif result == permissions.PERMISSION_SHOW_RATIONALE then -- In an educational UI, explain to the user why your app requires this -- permission for a specific feature to behave as expected, and what -- features are disabled if it's declined. In this UI, include a -- "cancel" or "no thanks" button that lets the user continue -- using your app without granting the permission. end ``` ### permissions.request *Type:* FUNCTION Requests permissions to be granted to this application. **Parameters** - `request_tbl` (table) - An array with constants that represent permissions. - `callback` (function) - A callback taking the following parameters - `self` (object) - The calling script - `result` (table) - A table where key is permission string and key is one of the following constants - `permissions.PERMISSION_GRANTED` - `permissions.PERMISSION_DENIED` **Examples** ``` local permissions_table = {"android.permission.WRITE_EXTERNAL_STORAGE", "android.permission.READ_CONTACTS"} permissions.request(permissions_table, function(self, result) for permission, result in pairs(result) do if result == permissions.PERMISSION_DENIED then -- You can directly ask for the permission. elseif result == permissions.PERMISSION_GRANTED then -- You can use the API that requires the permission. elseif result == permissions.PERMISSION_SHOW_RATIONALE then -- In an educational UI, explain to the user why your app requires this -- permission for a specific feature to behave as expected, and what -- features are disabled if it's declined. In this UI, include a -- "cancel" or "no thanks" button that lets the user continue -- using your app without granting the permission. end end end) ``` ### PERMISSION_GRANTED *Type:* VARIABLE The permission has been granted to the given package. ### PERMISSION_DENIED *Type:* VARIABLE The permission has not been granted to the given package. ### PERMISSION_SHOW_RATIONALE *Type:* VARIABLE Explain why your app needs the permission [Android doc](https://developer.android.com/training/permissions/requesting#explain) # extension-photon-fusion {#apis:extension-photon-fusion_fusion} **Namespace:** `fusion` **Language:** Lua **Type:** Extension Functions and constants for interacting with Photon Fusion ## API ### fusion.init *Type:* FUNCTION Initialize Fusion. **Parameters** - `app_id` (string) - `app_version` (string) ### fusion.init_from_settings *Type:* FUNCTION Initialize Fusion from game.project settings. ### fusion.connect *Type:* FUNCTION Connect Fusion. **Parameters** - `user` (string) - `region` (string) ### fusion.disconnect *Type:* FUNCTION Disonnect Fusion. ### fusion.reconnect *Type:* FUNCTION Reconnect Fusion. ### fusion.start *Type:* FUNCTION Start Fusion sync. ### fusion.stop *Type:* FUNCTION Stop Fusion sync. ### fusion.get_state *Type:* FUNCTION Get connection state. **Returns** - `number` - State ### fusion.get_disconnect_cause *Type:* FUNCTION Get disconnect cause. **Returns** - `number` - Cause ### fusion.join_or_create_room_random *Type:* FUNCTION Join or create random room. **Parameters** - `create_room_options` (table) - `matchmaking_options` (table) ### fusion.join_room_random *Type:* FUNCTION Join random room. **Parameters** - `matchmaking_options` (table) ### fusion.join_room *Type:* FUNCTION Join room. **Parameters** - `room_name` (string) - `join_room_options` (table) ### fusion.join_or_create_room *Type:* FUNCTION Join or create room. **Parameters** - `room_name` (string) - `create_room_options` (table) - `join_room_options` (table) ### fusion.create_room *Type:* FUNCTION Create room. **Parameters** - `room_name` (string) - `create_room_options` (table) ### fusion.leave_room *Type:* FUNCTION Leave room. **Parameters** - `will_come_back` (boolean) - `send_auth_cookie` (boolean) ### fusion.is_connected *Type:* FUNCTION Check if Fusion is connected. **Returns** - `boolean` ### fusion.is_running *Type:* FUNCTION Check if Fusion has config and is connected. **Returns** - `boolean` ### fusion.is_started *Type:* FUNCTION Check if Fusion is started. Fusion is considered started after a call to. `fusion.start()` has received a `EventOnFusionStart` event. **Returns** - `boolean` ### fusion.is_in_room *Type:* FUNCTION Check if Fusion is in a room. **Returns** - `boolean` ### fusion.enable_debug *Type:* FUNCTION Enable/disable debugging. **Parameters** - `enable` (boolean) ### fusion.register_scene_object *Type:* FUNCTION Register a scene object. **Parameters** - `scene` (number) - `factory_url` (string) - `owner_mode` (number) - `id` (string) ### fusion.spawn *Type:* FUNCTION Create a networked game object. This will spawn a game object in the same. Way as when calling factory.create(). The function will also register the spawned object with Fusion as if manually calling register_object() **Parameters** - `factory_url` (string) - `position` (vector3) - Initial position of created game object - `rotation` (quat) - Initial rotation of created game object - `scene` (number) - The scene to which this object belongs - `owner_mode` (number) - Owner mode of spawned object **Returns** - `hash` - Of the spawned game object ### fusion.despawn *Type:* FUNCTION Destroy a networked object. **Parameters** - `id` (string) ### fusion.register_object *Type:* FUNCTION Register an object. **Parameters** - `scene` (number) - `factory_url` (string) - `owner_mode` (number) - `id` (string) ### fusion.unregister_object *Type:* FUNCTION Unregister a previously registered object. **Parameters** - `id` (string) ### fusion.change_scene *Type:* FUNCTION Change scene. **Parameters** - `index` (number) - `sequence` (number) - `data` (string) ### fusion.rpc *Type:* FUNCTION Send RPC. **Parameters** - `target_player` (number) - 0 = all, specific PlayerId = targeted - `data` (string) **Returns** - `boolean` ### fusion.on_event *Type:* FUNCTION Set event listener. **Parameters** - `listener` (function) ### fusion.get_local_player_id *Type:* FUNCTION Get the player id of the local client **Returns** - `number` - Player id of the local client ### fusion.get_owner_id *Type:* FUNCTION Get the player id of the current owner of an object **Parameters** - `id` (string) - Id of the object to get the owner for **Returns** - `number` - Player id of the object's owner ### fusion.has_authority *Type:* FUNCTION Check if this client has authority over a game object. Use this to decide if user input should be handled or not. **Parameters** - `id` (string) **Returns** - `boolean` - Returns true if the client has authority ### fusion.has_owner *Type:* FUNCTION Check if an object has an owner **Parameters** - `id` (string) - Id of the object **Returns** - `boolean` - If the object has an owner ### fusion.want_authority *Type:* FUNCTION Signal desire for the local client to own an object **Parameters** - `claim_ownership` (boolean) - `id` (string) - Id of the object to own ### fusion.clear_owner_cooldown *Type:* FUNCTION Explicitly clear the ownership cooldown **Parameters** - `id` (string) - Id of the object to clear cooldown for ### fusion.set_send_rate *Type:* FUNCTION Set the send rate of an object. This decided how much bandwidth to allocate **Parameters** - `send_rate` (number) - `id` (string) - Id of the object to send rate for ### fusion.set_local_send_rate *Type:* FUNCTION Set the local send rate divisor for an object. A value of `1` means the object sends every tick (highest rate). A value of `16` means it sends every 16th tick (lowest rate). This is a client-side optimization -- the object still exists on all clients but consumes less bandwidth when you are not the active authority. **Parameters** - `send_rate` (number) - `id` (string) - Id of the object to send rate for ### fusion.reset_send_rate *Type:* FUNCTION Reset the send rate of an object. **Parameters** - `id` (string) - Id of the object to reset send rate for ### fusion.player_count *Type:* FUNCTION Get player count **Returns** - `number` - Number of players ### fusion.is_master_client *Type:* FUNCTION Get if this client is the room's master **Returns** - `boolean` - True if this client is the room's master ### fusion.get_rtt *Type:* FUNCTION Get round trip time **Returns** - `number` - Round trip time in seconds ### fusion.network_time_diff *Type:* FUNCTION Get raw offset between server time and local time. A positive value means the server clock is ahead of the local clock. **Returns** - `number` - Time diff ### fusion.set_global_interest_key *Type:* FUNCTION Set global visibility key for an object ### fusion.set_area_interest_key *Type:* FUNCTION Set area visibility key for an object ### fusion.set_user_interest_key *Type:* FUNCTION Set user visibility key for an object ### fusion.set_area_keys *Type:* FUNCTION Set area visibility keys **Parameters** - `keys` (table) - Area keys to set. Stored as a table of key value pairs (area_key->send_rate) ### fusion.add_user_key *Type:* FUNCTION Add a user visibility key ### fusion.remove_user_key *Type:* FUNCTION Remove a user visibility key from an object ### OWNERMODE_TRANSACTION *Type:* VARIABLE OWNERMODE_TRANSACTION ### OWNERMODE_PLAYERATTACHED *Type:* VARIABLE OWNERMODE_PLAYERATTACHED ### OWNERMODE_DYNAMIC *Type:* VARIABLE OWNERMODE_DYNAMIC ### OWNERMODE_MASTERCLIENT *Type:* VARIABLE OWNERMODE_MASTERCLIENT ### OWNERMODE_GAMEGLOBAL *Type:* VARIABLE OWNERMODE_GAMEGLOBAL ### STATE_DISCONNECTED *Type:* VARIABLE STATE_DISCONNECTED ### STATE_CONNECTING *Type:* VARIABLE STATE_CONNECTING ### STATE_CONNECTED *Type:* VARIABLE STATE_CONNECTED ### STATE_JOININGROOM *Type:* VARIABLE STATE_JOININGROOM ### STATE_INROOM *Type:* VARIABLE STATE_INROOM ### STATE_LEAVINGROOM *Type:* VARIABLE STATE_LEAVINGROOM ### STATE_DISCONNECTING *Type:* VARIABLE STATE_DISCONNECTING ### DISCONNECT_CAUSE_NONE *Type:* VARIABLE DISCONNECT_CAUSE_NONE ### DISCONNECT_CAUSE_DISCONNECTBYSERVERUSERLIMIT *Type:* VARIABLE DISCONNECT_CAUSE_DISCONNECTBYSERVERUSERLIMIT ### DISCONNECT_CAUSE_EXCEPTIONONCONNECT *Type:* VARIABLE DISCONNECT_CAUSE_EXCEPTIONONCONNECT ### DISCONNECT_CAUSE_DISCONNECTBYSERVER *Type:* VARIABLE DISCONNECT_CAUSE_DISCONNECTBYSERVER ### DISCONNECT_CAUSE_DISCONNECTBYSERVERLOGIC *Type:* VARIABLE DISCONNECT_CAUSE_DISCONNECTBYSERVERLOGIC ### DISCONNECT_CAUSE_TIMEOUTDISCONNECT *Type:* VARIABLE DISCONNECT_CAUSE_TIMEOUTDISCONNECT ### DISCONNECT_CAUSE_EXCEPTION *Type:* VARIABLE DISCONNECT_CAUSE_EXCEPTION ### DISCONNECT_CAUSE_INVALIDAUTHENTICATION *Type:* VARIABLE DISCONNECT_CAUSE_INVALIDAUTHENTICATION ### DISCONNECT_CAUSE_MAXCCUREACHED *Type:* VARIABLE DISCONNECT_CAUSE_MAXCCUREACHED ### DISCONNECT_CAUSE_INVALIDREGION *Type:* VARIABLE DISCONNECT_CAUSE_INVALIDREGION ### DISCONNECT_CAUSE_OPERATIONNOTALLOWEDINCURRENTSTATE *Type:* VARIABLE DISCONNECT_CAUSE_OPERATIONNOTALLOWEDINCURRENTSTATE ### DISCONNECT_CAUSE_CUSTOMAUTHENTICATIONFAILED *Type:* VARIABLE DISCONNECT_CAUSE_CUSTOMAUTHENTICATIONFAILED ### DISCONNECT_CAUSE_CLIENTVERSIONTOOOLD *Type:* VARIABLE DISCONNECT_CAUSE_CLIENTVERSIONTOOOLD ### DISCONNECT_CAUSE_CLIENTVERSIONINVALID *Type:* VARIABLE DISCONNECT_CAUSE_CLIENTVERSIONINVALID ### DISCONNECT_CAUSE_DASHBOARDVERSIONINVALID *Type:* VARIABLE DISCONNECT_CAUSE_DASHBOARDVERSIONINVALID ### DISCONNECT_CAUSE_AUTHENTICATIONTICKETEXPIRED *Type:* VARIABLE DISCONNECT_CAUSE_AUTHENTICATIONTICKETEXPIRED ### DISCONNECT_CAUSE_DISCONNECTBYOPERATIONLIMIT *Type:* VARIABLE DISCONNECT_CAUSE_DISCONNECTBYOPERATIONLIMIT ### EVENT_OBJECT_READY *Type:* VARIABLE EVENT_OBJECT_READY ### EVENT_SUB_OBJECT_CREATED *Type:* VARIABLE EVENT_SUB_OBJECT_CREATED ### EVENT_OBJECT_DESTROYED *Type:* VARIABLE EVENT_OBJECT_DESTROYED ### EVENT_SUB_OBJECT_DESTROYED *Type:* VARIABLE EVENT_SUB_OBJECT_DESTROYED ### EVENT_OBJECT_OWNER_CHANGED *Type:* VARIABLE EVENT_OBJECT_OWNER_CHANGED ### EVENT_OBJECT_PREDICTION_OVERRIDE *Type:* VARIABLE EVENT_OBJECT_PREDICTION_OVERRIDE ### EVENT_LOBBY_STATS *Type:* VARIABLE EVENT_LOBBY_STATS ### EVENT_ROOM_JOINED *Type:* VARIABLE EVENT_ROOM_JOINED ### EVENT_ROOM_LEFT *Type:* VARIABLE EVENT_ROOM_LEFT ### EVENT_RPC *Type:* VARIABLE EVENT_RPC ### EVENT_SCENE_CHANGE *Type:* VARIABLE EVENT_SCENE_CHANGE ### EVENT_DESTROYED_MAP_ACTOR *Type:* VARIABLE EVENT_DESTROYED_MAP_ACTOR ### EVENT_INTEREST_ENTER *Type:* VARIABLE EVENT_INTEREST_ENTER ### EVENT_INTEREST_EXIT *Type:* VARIABLE EVENT_INTEREST_EXIT ### EVENT_FORCED_DISCONNECT *Type:* VARIABLE EVENT_FORCED_DISCONNECT ### EVENT_FUSION_START *Type:* VARIABLE EVENT_FUSION_START ### EVENT_CONNECTED *Type:* VARIABLE EVENT_CONNECTED ### EVENT_DISCONNECTED *Type:* VARIABLE EVENT_DISCONNECTED # extension-photon-realtime {#apis:extension-photon-realtime_realtime} **Namespace:** `realtime` **Language:** Lua **Type:** Extension Functions and constants for interacting with Photon Realtime ## API ### realtime.init *Type:* FUNCTION Initialize Realtime by creating a load balanced client **Parameters** - `app_id` (string) - `app_version` (string) - `listener` (function) ### realtime.connect *Type:* FUNCTION Connect to the server. **Parameters** - `options` (table) - Table with connection options - `username` (string) - `use_datagram_encryption` (boolean) - `server_type` (number) - See SERVER_TYPE_* enums - `server_address` (string) - The IP address or domain name and optionally the port number to connect to. IP addresses can be in IPv4 or IPv6 format - `auth_data` (string) - Sets the HTTP POST data, that will be forwarded to the authentication service, to the provided data. - `auth_parameters` (string) - The HTTP GET parameters that will be forwarded to the authentication service to the provided parameters. - `auth_type` (number) - The type of the "Custom Authentication" service that will be used. See AUTH_* enums ### realtime.update *Type:* FUNCTION Update Realtime. Call this from a script component. ### realtime.disconnect *Type:* FUNCTION Disconnect from server. ### realtime.join_lobby *Type:* FUNCTION Join lobby. **Parameters** - `lobby_name` (string) - `lobby_type` (number) ### realtime.leave_lobby *Type:* FUNCTION Leave lobby. ### realtime.create_room *Type:* FUNCTION Create room. **Parameters** - `game_id` (string) - The name to create a room with. Must be unique and not in use or the room can't be created. If this is an empty string, then the server will assign a GUID as name. - `room_options` (table) - `is_visible` (boolean) - `is_open` (boolean) - `supress_room_events` (boolean) - `max_players` (number) - `player_ttl` (number) - `empty_room_ttl` (number) - `lobby_type` (number) - Realtime.LOBBYTYPE_* enum - `lobby_name` (string) - `publish_user_id` (string) - `direct_mode` (numbmer) - Realtime.DIRECTMODE_* enum - `props_listed_in_lobby` (table) - `custom_room_properties` (table) - `expected_users` (table) ### realtime.join_room *Type:* FUNCTION Join room. **Parameters** - `game_id` (string) - The name to create a room with. Must be unique and not in use or the room can't be created. If this is an empty string, then the server will assign a GUID as name. - `join_options` (table) - `rejoin` (boolean) - `cache_slice_index` (number) - `expected_users` (table) ### realtime.join_or_create_room *Type:* FUNCTION Join or create room. **Parameters** - `game_id` (string) - The name to create a room with. Must be unique and not in use or the room can't be created. If this is an empty string, then the server will assign a GUID as name. - `room_options` (table) - `is_visible` (boolean) - `is_open` (boolean) - `supress_room_events` (boolean) - `max_players` (number) - `player_ttl` (number) - `empty_room_ttl` (number) - `lobby_type` (number) - Realtime.LOBBYTYPE_* enum - `lobby_name` (string) - `publish_user_id` (string) - `direct_mode` (numbmer) - Realtime.DIRECTMODE_* enum - `props_listed_in_lobby` (table) - `custom_room_properties` (table) - `join_options` (table) - `custom_room_properties` (table) - `max_players` (number) - `matchmaking_mode` (number) - Realtime.MATCHMAKINGMODE_* enum - `lobby_name` (string) - `lobby_type` (number) - Realtime.LOBBYTYPE_* enum - `sql_lobby_filter` (string) - `expected_users` (table) ### realtime.join_or_create_random_room *Type:* FUNCTION Join or create random room. **Parameters** - `game_id` (string) - The name to create a room with. Must be unique and not in use or the room can't be created. If this is an empty string, then the server will assign a GUID as name. - `room_options` (table) - `is_visible` (boolean) - `is_open` (boolean) - `supress_room_events` (boolean) - `max_players` (number) - `player_ttl` (number) - `empty_room_ttl` (number) - `lobby_type` (number) - Realtime.LOBBYTYPE_* enum - `lobby_name` (string) - `publish_user_id` (string) - `direct_mode` (numbmer) - Realtime.DIRECTMODE_* enum - `props_listed_in_lobby` (table) - `custom_room_properties` (table) - `join_options` (table) - `custom_room_properties` (table) - `max_players` (number) - `matchmaking_mode` (number) - Realtime.MATCHMAKINGMODE_* enum - `lobby_name` (string) - `lobby_type` (number) - Realtime.LOBBYTYPE_* enum - `sql_lobby_filter` (string) - `expected_users` (table) ### realtime.join_random_room *Type:* FUNCTION Join random room. **Parameters** - `join_options` (table) - `custom_room_properties` (table) - `max_players` (number) - `matchmaking_mode` (number) - Realtime.MATCHMAKINGMODE_* enum - `lobby_name` (string) - `lobby_type` (number) - Realtime.LOBBYTYPE_* enum - `sql_lobby_filter` (string) - `expected_users` (table) ### realtime.leave_room *Type:* FUNCTION Leave room. **Parameters** - `will_come_back` (boolean) - `send_auth_cookie` (boolean) ### realtime.get_room_list *Type:* FUNCTION Get room list. ### realtime.raise_event *Type:* FUNCTION Sends in-game data to other players in the game. **Parameters** - `reliable` (boolean) - `parameter` (number) - `event_code` (number) - `options` (table) - (channel_id, event_caching, receiver_group, interest_group, cache_slice_index, target_players, web_flags, encrypt) - `channel_id` (number) - `event_caching` (number) - `receiver_group` (number) - `interest_group` (number) - `cache_slice_index` (number) - `target_players` (number) - `web_flags` (number) - `encrypt` (boolean) **Returns** - `boolea` ### realtime.set_auto_join_lobby *Type:* FUNCTION Set the auto join lobby flag. The value of the autoJoinLobby flag determines if the client will automatically join the default lobby whenever it has successfully connected and whenever it leaves a game room. **Parameters** - `auto_join` (boolean) ### EVENT_CONNECTIONERRORRETURN *Type:* VARIABLE EVENT_CONNECTIONERRORRETURN ### EVENT_CLIENTERRORRETURN *Type:* VARIABLE EVENT_CLIENTERRORRETURN ### EVENT_WARNINGRETURN *Type:* VARIABLE EVENT_WARNINGRETURN ### EVENT_SERVERERRORRETURN *Type:* VARIABLE EVENT_SERVERERRORRETURN ### EVENT_JOINROOMEVENTACTION *Type:* VARIABLE EVENT_JOINROOMEVENTACTION ### EVENT_LEAVEROOMEVENTACTION *Type:* VARIABLE EVENT_LEAVEROOMEVENTACTION ### EVENT_CUSTOMEVENTACTION *Type:* VARIABLE EVENT_CUSTOMEVENTACTION ### EVENT_CONNECTRETURN *Type:* VARIABLE EVENT_CONNECTRETURN ### EVENT_DISCONNECTRETURN *Type:* VARIABLE EVENT_DISCONNECTRETURN ### EVENT_CREATEROOMRETURN *Type:* VARIABLE EVENT_CREATEROOMRETURN ### EVENT_JOINORCREATEROOMRETURN *Type:* VARIABLE EVENT_JOINORCREATEROOMRETURN ### EVENT_JOINRANDOMORCREATEROOMRETURN *Type:* VARIABLE EVENT_JOINRANDOMORCREATEROOMRETURN ### EVENT_JOINROOMRETURN *Type:* VARIABLE EVENT_JOINROOMRETURN ### EVENT_JOINRANDOMROOMRETURN *Type:* VARIABLE EVENT_JOINRANDOMROOMRETURN ### EVENT_LEAVEROOMRETURN *Type:* VARIABLE EVENT_LEAVEROOMRETURN ### EVENT_JOINLOBBYRETURN *Type:* VARIABLE EVENT_JOINLOBBYRETURN ### EVENT_LEAVELOBBYRETURN *Type:* VARIABLE EVENT_LEAVELOBBYRETURN ### EVENT_ONFINDFRIENDSRESPONSE *Type:* VARIABLE EVENT_ONFINDFRIENDSRESPONSE ### EVENT_ONLOBBYSTATSRESPONSE *Type:* VARIABLE EVENT_ONLOBBYSTATSRESPONSE ### EVENT_WEBRPCRETURN *Type:* VARIABLE EVENT_WEBRPCRETURN ### EVENT_ONROOMLISTUPDATE *Type:* VARIABLE EVENT_ONROOMLISTUPDATE ### EVENT_ONROOMPROPERTIESCHANGE *Type:* VARIABLE EVENT_ONROOMPROPERTIESCHANGE ### EVENT_ONPLAYERPROPERTIESCHANGE *Type:* VARIABLE EVENT_ONPLAYERPROPERTIESCHANGE ### EVENT_ONAPPSTATSUPDATE *Type:* VARIABLE EVENT_ONAPPSTATSUPDATE ### EVENT_ONLOBBYSTATSUPDATE *Type:* VARIABLE EVENT_ONLOBBYSTATSUPDATE ### EVENT_ONCACHESLICECHANGED *Type:* VARIABLE EVENT_ONCACHESLICECHANGED ### EVENT_ONMASTERCLIENTCHANGED *Type:* VARIABLE EVENT_ONMASTERCLIENTCHANGED ### EVENT_ONCUSTOMAUTHENTICATIONINTERMEDIATESTEP *Type:* VARIABLE EVENT_ONCUSTOMAUTHENTICATIONINTERMEDIATESTEP ### EVENT_ONAVAILABLEREGIONS *Type:* VARIABLE EVENT_ONAVAILABLEREGIONS ### EVENT_ONSECRETRECEIVAL *Type:* VARIABLE EVENT_ONSECRETRECEIVAL ### EVENT_ONDIRECTCONNECTIONESTABLISHED *Type:* VARIABLE EVENT_ONDIRECTCONNECTIONESTABLISHED ### EVENT_ONDIRECTCONNECTIONFAILEDTOESTABLISH *Type:* VARIABLE EVENT_ONDIRECTCONNECTIONFAILEDTOESTABLISH ### EVENT_ONDIRECTMESSAGE *Type:* VARIABLE EVENT_ONDIRECTMESSAGE ### EVENT_ONCUSTOMOPERATIONRESPONSE *Type:* VARIABLE EVENT_ONCUSTOMOPERATIONRESPONSE ### EVENT_ONGETROOMLISTRESPONSE *Type:* VARIABLE EVENT_ONGETROOMLISTRESPONSE ### AUTH_CUSTOM *Type:* VARIABLE Use a custom authentication service. ### AUTH_STEAM *Type:* VARIABLE Authenticates users by their Steam Account. Pass L"ticket=[ticket]" to setParameters(). ### AUTH_FACEBOOK *Type:* VARIABLE Authenticates users by their Facebook Account. Pass L"token=[token]" to setParameters(). ### AUTH_OCULUS *Type:* VARIABLE Authenticates users by their Oculus Account. Pass L"userid=[userid]&nonce=[nonce]" to setParameters(). ### AUTH_PLAYSTATION_4 *Type:* VARIABLE Authenticates users by their PSN Account. Pass L"token=[token]&env=[env]&userName=[userName]" to setParameters(). ### AUTH_XBOX *Type:* VARIABLE Authenticates users by their XBox Network Account. Pass the XSTS token to setData(). ### AUTH_VIVEPORT *Type:* VARIABLE Authenticates users by their HTC Viveport Account and user token. Pass L"userToken=[userToken]" to setParameters(). ### AUTH_NINTENDO_SWITCH *Type:* VARIABLE Authenticates users by their Nintendo Account. Pass L"token=[token]&appversion=[appversion]" to setParameters(). The appversion is optional. ### AUTH_PLAYSTATION_5 *Type:* VARIABLE Authenticates users by their PSN Account. Pass L"token=[token]&env=[env]&userName=[userName]" to setParameters(). ### AUTH_EPIC *Type:* VARIABLE Authenticates users by their Epic Online Services (EOS) Account. Pass L"token=[token]&ownershipToken=[ownershipToken]" to setParameters(). The ownershipToken is optional. ### AUTH_FACEBOOK_GAMING *Type:* VARIABLE Authenticates users by their Facebook Account. Pass L"token=[token]" to setParameters(). ### AUTH_NONE *Type:* VARIABLE Disables custom authentication. ### SERVER_TYPE_NAME_SERVER *Type:* VARIABLE Photon Cloud and for self-hosted Photon 5 or higher Server instances ### SERVER_TYPE_MASTER_SERVER *Type:* VARIABLE Self-hosted Photon 4 Server instances ### MATCHMAKINGMODE_FILL_ROOM *Type:* VARIABLE Fills up rooms (oldest first) to get players together as fast as possible. Default. Makes most sense with MaxPlayers > 0 and games that can only start with more players. ### MATCHMAKINGMODE_SERIAL_MATCHING *Type:* VARIABLE Distributes players across available rooms sequentially but takes filters into account. Without filters, rooms get players evenly distributed. ### MATCHMAKINGMODE_RANDOM_MATCHING *Type:* VARIABLE Joins a (fully) random room. Expected properties must match, but aside from this, any available room might be selected. ### LOBBYTYPE_DEFAULT *Type:* VARIABLE This lobby type is used unless another lobby type is specified. Room lists will be sent and Client::opJoinRandomRoom() can filter by matching properties. ### LOBBYTYPE_SQL_LOBBY *Type:* VARIABLE This lobby type lists rooms like type DEFAULT but SQL-like "where" clauses for filtering can be used with Client::opJoinRandomRoom(). This allows 'bigger', 'less', 'or' and 'and' combinations. ### LOBBYTYPE_ASYNC_RANDOM_LOBBY *Type:* VARIABLE This lobby does not send room lists. It is only used for Client::opJoinRandomRoom(). It keeps rooms available for matchmaking for a while even when there are only inactive users left. ### DIRECTMODE_NONE *Type:* VARIABLE Do not create any 2p2 connections between the clients. This is the default. ### DIRECTMODE_ALL_TO_OTHERS *Type:* VARIABLE Each client establishes a direct connection with every other client inside the room. ### DIRECTMODE_MASTER_TO_OTHERS *Type:* VARIABLE The master client establishes a direct connection with every other client inside the room. All other clients only establish a direct connection with the master client but not with each other. ### DIRECTMODE_ALL_TO_ALL *Type:* VARIABLE Each client establishes a direct connection with every client inside the room, including itself. ### DIRECTMODE_MASTER_TO_ALL *Type:* VARIABLE The master client establishes a direct connection with every client inside the room, including itself. All other clients only establish a direct connection with the master client but not with each other. # extension-poki-sdk {#apis:extension-poki-sdk_poki_sdk} **Namespace:** `poki_sdk` **Language:** Lua **Type:** Extension Functions and constants for interacting with Poki SDK APIs ## API ### poki_sdk.gameplay_start *Type:* FUNCTION ### poki_sdk.gameplay_stop *Type:* FUNCTION ### poki_sdk.commercial_break *Type:* FUNCTION **Parameters** - `callback` (function) - `self` (object) - The calling script instance - `status` (number) - One of the statuses: `poki_sdk.COMMERCIAL_BREAK_START`, `poki_sdk.COMMERCIAL_BREAK_SUCCESS` ### poki_sdk.rewarded_break *Type:* FUNCTION **Parameters** - `size` (string) - The size of the reward. Accepted values are small, medium and large. Optional. Default is small. - `callback` (function) - `self` (object) - The calling script instance - `status` (number) - One of the statuses: `poki_sdk.REWARDED_BREAK_ERROR`, `poki_sdk.REWARDED_BREAK_START`, `poki_sdk.REWARDED_BREAK_SUCCESS` ### poki_sdk.set_debug *Type:* FUNCTION **Parameters** - `is_debug` (boolean) ### poki_sdk.capture_error *Type:* FUNCTION **Parameters** - `error` (string) ### poki_sdk.shareable_url *Type:* FUNCTION **Parameters** - `params` (table) - `callback` (function) ### poki_sdk.get_url_param *Type:* FUNCTION **Parameters** - `key` (string) ### poki_sdk.measure *Type:* FUNCTION **Parameters** - `category` (string) - `what` (string) - `action` (string) ### poki_sdk.move_pill *Type:* FUNCTION **Parameters** - `topPercent` (number) - `topPx` (number) ### poki_sdk.open_external_link *Type:* FUNCTION **Parameters** - `url` (string) ### poki_sdk.openExternalLink *Type:* FUNCTION **Parameters** - `url` (string) ### COMMERCIAL_BREAK_SUCCESS *Type:* VARIABLE ### COMMERCIAL_BREAK_START *Type:* VARIABLE ### REWARDED_BREAK_ERROR *Type:* VARIABLE ### REWARDED_BREAK_SUCCESS *Type:* VARIABLE ### REWARDED_BREAK_START *Type:* VARIABLE # extension-push {#apis:extension-push_push} **Namespace:** `push` **Language:** Lua **Type:** Extension Functions and constants for interacting with local, as well as Apple''s and Google''s push notification services. These API's only exist on mobile platforms. [icon:ios] [icon:android] ## API ### push.register *Type:* FUNCTION Send a request for push notifications. Note that the notifications table parameter is iOS only and will be ignored on Android. **Parameters** - `notifications` (table) - The types of notifications to listen to. [icon:ios] - `callback` (function) - Register callback function. - `self` (object) - The current object. - `token` (string) - The returned push token if registration is successful. - `error` (table) - A table containing eventual error information. **Examples** Register for push notifications on iOS. Note that the token needs to be converted on this platform. ``` local function push_listener(self, payload, origin) -- The payload arrives here. end function init(self) local alerts = {push.NOTIFICATION_BADGE, push.NOTIFICATION_SOUND, push.NOTIFICATION_ALERT} push.register(alerts, function (self, token, error) if token then -- NOTE: %02x to pad byte with leading zero local token_string = "" for i = 1,#token do token_string = token_string .. string.format("%02x", string.byte(token, i)) end print(token_string) push.set_listener(push_listener) else -- Push registration failed. print(error.error) end end ``` Register for push notifications on Android. ``` local function push_listener(self, payload, origin) -- The payload arrives here. end function init(self) push.register({}, function (self, token, error) if token then print(token) push.set_listener(push_listener) else -- Push registration failed. print(error.error) end end) end ``` ### push.set_listener *Type:* FUNCTION Sets a listener function to listen to push notifications. **Parameters** - `listener` (function) - Listener callback function. - `self` (object) - The current object. - `payload` (table) - The push payload - `origin` (constant) - Origin of the push that can be one of the predefined constants below - `push.ORIGIN_LOCAL` - `push.ORIGIN_REMOTE` - `activated` (boolean) - If the application was activated via the notification. **Examples** Set the push notification listener. ``` local function push_listener(self, payload, origin, activated) -- The payload arrives here. pprint(payload) if origin == push.ORIGIN_LOCAL then -- This was a local push ... end if origin == push.ORIGIN_REMOTE then -- This was a remote push ... end end local init(self) ... -- Assuming that push.register() has been successfully called earlier push.set_listener(push_listener) end ``` ### push.set_badge_count *Type:* FUNCTION Set the badge count for application icon. This function is only available on iOS. [icon:ios] **Parameters** - `count` (number) - Badge count ### push.schedule *Type:* FUNCTION Local push notifications are scheduled with this function. The returned `id` value is uniquely identifying the scheduled notification and can be stored for later reference. **Parameters** - `time` (number) - Number of seconds into the future until the notification should be triggered. - `title` (string) - Localized title to be displayed to the user if the application is not running. - `alert` (string) - Localized body message of the notification to be displayed to the user if the application is not running. - `payload` (string) - JSON string to be passed to the registered listener function. - `notification_settings` (table) - Table with notification and platform specific fields - `action` (string) - The alert action string to be used as the title of the right button of the alert or the value of the unlock slider, where the value replaces "unlock" in "slide to unlock" text. [icon:ios] - `badge_count` (number) - The numeric value of the icon badge. [icon:ios] - `priority` (number) - The priority is a hint to the device UI about how the notification should be displayed. There are five priority levels, from -2 to 2 where -1 is the lowest priority and 2 the highest. Unless specified, a default priority level of 2 is used. [icon:android] **Returns** - `number` - Unique id that can be used to cancel or inspect the notification - `string` - Error string if something went wrong, otherwise nil **Examples** This example demonstrates how to schedule a local notification: ``` -- Schedule a local push in 3 seconds local payload = '{ "data" : { "field" : "Some value", "field2" : "Other value" } }' id, err = push.schedule(3, "Update!", "There are new stuff in the app", payload, { action = "check it out" }) if err then -- Something went wrong ... end ``` ### push.cancel *Type:* FUNCTION Use this function to cancel a previously scheduled local push notification. The notification is identified by a numeric id as returned by `push.schedule()`. **Parameters** - `id` (number) - The numeric id of the local push notification ### push.cancel_all_issued *Type:* FUNCTION Use this function to cancel a previously issued local push notifications. ### push.get_scheduled *Type:* FUNCTION Returns a table with all data associated with a specified local push notification. The notification is identified by a numeric id as returned by `push.schedule()`. **Parameters** - `id` (number) - The numeric id of the local push notification. **Returns** - `table` - Table with all data associated with the notification. ### push.get_all_scheduled *Type:* FUNCTION Returns a table with all data associated with all scheduled local push notifications. The table contains key, value pairs where the key is the push notification id and the value is a table with the notification data, corresponding to the data given by `push.get_scheduled(id)`. **Returns** - `table` - Table with all data associated with all scheduled notifications. ### NOTIFICATION_BADGE *Type:* VARIABLE Badge notification type. ### NOTIFICATION_SOUND *Type:* VARIABLE Sound notification type. ### NOTIFICATION_ALERT *Type:* VARIABLE Alert notification type. ### ORIGIN_LOCAL *Type:* VARIABLE Local push origin. ### ORIGIN_REMOTE *Type:* VARIABLE Remote push origin. ### PRIORITY_MIN *Type:* VARIABLE This priority is for items might not be shown to the user except under special circumstances, such as detailed notification logs. Only available on Android. [icon:android] ### PRIORITY_LOW *Type:* VARIABLE Priority for items that are less important. Only available on Android. [icon:android] ### PRIORITY_DEFAULT *Type:* VARIABLE The default notification priority. Only available on Android. [icon:android] ### PRIORITY_HIGH *Type:* VARIABLE Priority for more important notifications or alerts. Only available on Android. [icon:android] ### PRIORITY_MAX *Type:* VARIABLE Set this priority for your application's most important items that require the user's prompt attention or input. Only available on Android. [icon:android] # extension-review {#apis:extension-review_review} **Namespace:** `review` **Language:** Lua **Type:** Extension Functions and constants for interacting with review APIs ## API ### review.request_review *Type:* FUNCTION Open native review/rating popup ### review.is_supported *Type:* FUNCTION Available only on iOS 10.3+. Android 5.0+ (API 21+) and the Google Play Store has to be installed. # extension-rive {#apis:extension-rive_rive} **Namespace:** `rive` **Language:** Lua **Type:** Extension Rive animation helpers exposed to Lua scripts ## API ### rive.pointer_move *Type:* FUNCTION Lua wrapper for pointer movement. **Parameters** - `url` (url) - Component receiving the pointer move. - `x` (number) - Pointer x coordinate in component space. - `y` (number) - Pointer y coordinate in component space. ### rive.pointer_up *Type:* FUNCTION Lua wrapper for pointer up events. **Parameters** - `url` (url) - Component receiving the pointer release. - `x` (number) - Pointer x coordinate. - `y` (number) - Pointer y coordinate. ### rive.pointer_down *Type:* FUNCTION Lua wrapper for pointer down events. **Parameters** - `url` (url) - Component receiving the pointer press. - `x` (number) - Pointer x coordinate. - `y` (number) - Pointer y coordinate. ### rive.pointer_exit *Type:* FUNCTION Lua wrapper for pointer exit events. **Parameters** - `url` (url) - Component receiving the pointer leave. - `x` (number) - Pointer x coordinate. - `y` (number) - Pointer y coordinate. ### rive.get_projection_matrix *Type:* FUNCTION Returns the projection matrix in render coordinates. ### rive.set_file_listener *Type:* FUNCTION Sets or clears the global file listener callback. **Parameters** - `callback` (function(self, event, data) | nil) - Callback invoked for file system events; pass nil to disable. - `self` (object) - The calling script instance. - `event` (string) - One of onFileLoaded, onFileDeleted, onFileError, onArtboardInstantiated, onArtboardsListed, onViewModelsListed, onViewModelInstanceInstantiated, onViewModelInstanceNamesListed, onViewModelPropertiesListed, onViewModelEnumsListed - `data` (table) - Additional fields vary by event. Common keys include - `file` (FileHandle) - File handle involved in the event. - `artboard` (ArtboardHandle) - Instantiated artboard handle, when applicable. - `viewModel` (ViewModelInstanceHandle) - Instantiated view model instance handle, when applicable. - `viewModelName` (string) - View model name for the request, when applicable. - `instanceNames` (table) - Array of instance name strings. - `artboardNames` (table) - Array of artboard name strings. - `properties` (table) - Array of property metadata tables. - `enums` (table) - Array of enum definitions. - `error` (string) - Error message when a failure occurs. ### rive.get_file *Type:* FUNCTION Returns the Rive file handle tied to the component. **Parameters** - `url` (url) - Component whose file handle to query. ### rive.set_artboard *Type:* FUNCTION Switches the active artboard for the component. **Parameters** - `url` (url) - Component using the artboard. - `name` (string | nil) - Name of the artboard to create and set. Pass nil to create a default artboard. ### rive.get_artboard *Type:* FUNCTION Queries the current artboard handle for the component. **Parameters** - `url` (url) - Component whose artboard handle to return. ### rive.set_state_machine *Type:* FUNCTION Selects a state machine by name on the component. **Parameters** - `url` (url) - Component owning the state machine. - `name` (string | nil) - Name of the state machine to create and set. Pass nil to create a default state machine. ### rive.get_state_machine *Type:* FUNCTION Returns the active state machine handle for the component. **Parameters** - `url` (url) - Component whose active state machine to query. ### rive.set_view_model_instance *Type:* FUNCTION Selects a default view model instance by name. **Parameters** - `url` (url) - Component owning the view model instance. - `name` (string) - View model name whose default instance should be activated. ### rive.get_view_model_instance *Type:* FUNCTION Returns the handle of the currently bound view model instance. **Parameters** - `url` (url) - Component whose view model instance handle to query. # extension-safearea {#apis:extension-safearea_safearea} **Namespace:** `safearea` **Language:** Lua **Type:** Extension Defold native extension that will change the view/render of a game to fit into the safe area on iPhones and Android(API 28+) with notch. ## API ### safearea.set_background_color *Type:* FUNCTION set background color in runtime **Parameters** - `color` (vector4) - Color will be used as background color. ### safearea.get_insets *Type:* FUNCTION returns table with top, left, right, bottom values of insets and status **Returns** - `table` ### safearea.get_corners_radius *Type:* FUNCTION returns a table with `top_left`, `top_right`, `bottom_left`, and `bottom_right` values of rounded corners and status. **Returns** - `table` ### STATUS_OK *Type:* VARIABLE ### STATUS_NOT_AVAILABLE *Type:* VARIABLE ### STATUS_NOT_READY_YET *Type:* VARIABLE # extension-siwa {#apis:extension-siwa_siwa} **Namespace:** `siwa` **Language:** Lua **Type:** Extension Functions and constants for interacting Sign in with Apple. [icon:ios] ## API ### siwa.is_supported *Type:* FUNCTION Check if Sign in with Apple is available (iOS 13+). ### siwa.get_credential_state *Type:* FUNCTION Get the credential state of a user. **Parameters** - `user_id` (string) - User id to get credential state for. - `callback` (function) - Credential state callback function. - `self` (object) - The current object. - `state` (table) - The credential state (user_id, credential_state) **Examples** ``` siwa.get_credential_state(id, function(self, data) if data.credential_state == siwa.STATE_AUTHORIZED then print("User has still authorized the application", data.user_id) elseif data.credential_state == siwa.STATE_REVOKED then print("User has revoked authorization for the application", data.user_id) end end) ``` ### siwa.authenticate *Type:* FUNCTION Show the Sign in with Apple UI **Parameters** - `callback` (function) - Authentication callback function. - `self` (object) - The current object. - `state` (table) - The authentication result data (user_id, identity_token, email, first_name, family_name, status, result) **Examples** ``` siwa.authenticate(function(self, data) print(data.identity_token) print(data.user_id) print(data.first_name, data.family_name) print(data.email) if data.user_status == siwa.STATUS_LIKELY_REAL then print("Likely a real person") end end) ``` ### STATE_NOT_FOUND *Type:* VARIABLE The user can’t be found. ### STATE_UNKNOWN *Type:* VARIABLE Unknown credential state. ### STATE_AUTHORIZED *Type:* VARIABLE The user is authorized. ### STATE_REVOKED *Type:* VARIABLE Authorization for the given user has been revoked. ### STATUS_UNKNOWN *Type:* VARIABLE The system hasn’t determined whether the user might be a real person. ### STATUS_UNSUPPORTED *Type:* VARIABLE The system can’t determine this user’s status as a real person. ### STATUS_LIKELY_REAL *Type:* VARIABLE The user appears to be a real person. # extension-spine {#apis:extension-spine_gui} **Namespace:** `gui` **Language:** Lua **Type:** Extension Functions and constants for interacting with Spine models in GUI ## API ### gui.new_spine_node *Type:* FUNCTION Dynamically create a new spine node. **Parameters** - `pos` (vector3 | vector4) - node position - `spine_scene` (string | hash) - spine scene id ### gui.play_spine_anim *Type:* FUNCTION Starts a spine animation. **Parameters** - `node` (node) - spine node that should play the animation - `animation_id` (string | hash) - id of the animation to play - `playback` (constant) - playback mode - `gui.PLAYBACK_ONCE_FORWARD` - `gui.PLAYBACK_ONCE_BACKWARD` - `gui.PLAYBACK_ONCE_PINGPONG` - `gui.PLAYBACK_LOOP_FORWARD` - `gui.PLAYBACK_LOOP_BACKWARD` - `gui.PLAYBACK_LOOP_PINGPONG` - `play_properties` (table) - optional table with properties - `blend_duration` (number) - The duration of a linear blend between the current and new animation - `offset` (number) - The normalized initial value of the animation cursor when the animation starts playing - `playback_rate` (number) - The rate with which the animation will be played. Must be positive - `complete_function` (function(self, node)) - function to call when the animation has completed ### gui.cancel_spine *Type:* FUNCTION cancel a spine animation **Parameters** - `node` (node) - spine node that should cancel its animation ### gui.get_spine_bone *Type:* FUNCTION The returned node can be used for parenting and transform queries. This function has complexity O(n), where n is the number of bones in the spine model skeleton. **Parameters** - `node` (node) - spine node to query for bone node - `bone_id` (string | hash) - id of the corresponding bone ### gui.set_spine_scene *Type:* FUNCTION Set the spine scene on a spine node. The spine scene must be mapped to the gui scene in the gui editor. **Parameters** - `node` (node) - node to set spine scene for - `spine_scene` (string | hash) - spine scene id ### gui.get_spine_scene *Type:* FUNCTION Returns the spine scene id of the supplied node. This is currently only useful for spine nodes. The returned spine scene must be mapped to the gui scene in the gui editor. **Parameters** - `node` (node) - node to get texture from ### gui.set_spine_skin *Type:* FUNCTION Sets the spine skin on a spine node. **Parameters** - `node` (node) - node to set the spine skin on - `spine_skin` (string | hash) - spine skin id **Examples** Change skin of a Spine node ``` function init(self) gui.set_spine_skin(gui.get_node("spine_node"), "monster") end ``` ### gui.add_spine_skin *Type:* FUNCTION Add a spine skin on a spine node to another skin on the same node. **Parameters** - `node` (node) - node having both skins - `spine_skin_a` (string | hash) - spine skin id that recieves other skin - `spine_skin_b` (string | hash) - spine skin id that will be added **Examples** Add skin of a Spine node to another skin ``` function init(self) gui.add_spine_skin(gui.get_node("spine_node"), "monster_head", "monster_body") end ``` ### gui.copy_spine_skin *Type:* FUNCTION Copy a spine skin on a spine node to another skin on the same node. **Parameters** - `node` (node) - node having both skins - `spine_skin_a` (string | hash) - spine skin id that copies other skin - `spine_skin_b` (string | hash) - spine skin id that will be copied **Examples** Copy skin of a Spine node to another skin ``` function init(self) gui.copy_spine_skin(gui.get_node("spine_node"), "monster_head", "monster_body") end ``` ### gui.clear_spine_skin *Type:* FUNCTION Clear a spine skin on a spine node of all attachments and constraints **Parameters** - `node` (node) - node having both skins - `spine_skin` (string | hash) - spine skin id **Examples** Clear skin of a Spine node ``` function init(self) gui.clear_spine_skin(gui.get_node("spine_node"), "monster") end ``` ### gui.get_spine_skin *Type:* FUNCTION Gets the spine skin of a spine node **Parameters** - `node` (node) - node to get spine skin from ### gui.get_spine_animation *Type:* FUNCTION Gets the playing animation on a spine node **Parameters** - `node` (node) - node to get spine skin from ### gui.set_spine_cursor *Type:* FUNCTION This is only useful for spine nodes. The cursor is normalized. **Parameters** - `node` (node) - spine node to set the cursor for - `cursor` (number) - cursor value ### gui.get_spine_cursor *Type:* FUNCTION This is only useful for spine nodes. Gets the normalized cursor of the animation on a spine node. **Parameters** - `node` (node) - spine node to get the cursor for (node) ### gui.set_spine_playback_rate *Type:* FUNCTION This is only useful for spine nodes. Sets the playback rate of the animation on a spine node. Must be positive. **Parameters** - `node` (node) - spine node to set the cursor for - `playback_rate` (number) - playback rate ### gui.get_spine_playback_rate *Type:* FUNCTION This is only useful for spine nodes. Gets the playback rate of the animation on a spine node. **Parameters** - `node` (node) - spine node to set the cursor for ### gui.set_spine_attachment *Type:* FUNCTION This is only useful for spine nodes. Sets an attachment to a slot on a spine node. **Parameters** - `node` (node) - spine node to set the slot for - `slot` (string | hash) - slot name - `attachment` (string | hash) - attachment name. May be nil. ### gui.set_spine_slot_color *Type:* FUNCTION This is only useful for spine nodes. Sets a tint for all attachments on a slot **Parameters** - `node` (node) - spine node to set the slot for - `slot` (string | hash) - slot name - `color` (vector4) - target color. ### gui.spine_physics_translate *Type:* FUNCTION Apply a physics-based translation to the Spine GUI node. **Parameters** - `node` (node) - The Spine GUI node to translate. - `translation` (vector3) - The translation vector to apply to the Spine GUI node. ### gui.spine_physics_rotate *Type:* FUNCTION Apply a physics-based rotation to the Spine GUI node. **Parameters** - `node` (node) - The Spine GUI node to rotate. - `center` (vector3) - The center point around which to rotate. - `degrees` (number) - The rotation angle in degrees. ### gui.set_spine_ik_target_position *Type:* FUNCTION Sets a static (vector3) target position of an inverse kinematic (IK) object. **Parameters** - `node` (node) - the Spine GUI node containing the object - `ik_constraint_id` (string | hash) - id of the corresponding IK constraint object - `position` (vector3) - target position **Examples** The following example assumes that the Spine GUI node has id "spine_node". How to set the target IK position of the right_hand_constraint constraint object of the player object ``` function init(self) local pos = vmath.vector3(1, 2, 0) gui.set_spine_ik_target_position(gui.get_node("spine_node"), "right_hand_constraint", pos) end ``` ### gui.set_spine_ik_target *Type:* FUNCTION Sets a GUI node as target position of an inverse kinematic (IK) object. As the target GUI node's position is updated, the constraint object is updated with the new position. **Parameters** - `node` (node) - the Spine GUI node containing the object - `ik_constraint_id` (string | hash) - id of the corresponding IK constraint object - `target_node` (node) - target GUI node **Examples** The following example assumes that the Spine GUI node has id "spine_node". How to set the target IK position of the right_hand_constraint constraint object to follow the position of GUI node with id "target_node" ``` function init(self) local spine_node = gui.get_node("spine_node") local target_node = gui.get_node("target_node") gui.set_spine_ik_target(spine_node, "right_hand_constraint", target_node) end ``` ### gui.reset_spine_ik_target *Type:* FUNCTION Resets any previously set IK target of a Spine GUI node, the position will be reset to the original position from the spine scene. **Parameters** - `node` (node) - the Spine GUI node containing the object - `ik_constraint_id` (string | hash) - id of the corresponding IK constraint object **Examples** The following example assumes that the Spine GUI node has id "spine_node". A player no longer has an item in hand, that previously was controlled through IK, let's reset the IK of the right hand. ``` function player_lost_item(self) gui.reset_spine_ik_target(gui.get_node("spine_node"), "right_hand_constraint") end ``` # extension-spine {#apis:extension-spine_spine} **Namespace:** `spine` **Language:** Lua **Type:** Extension Functions and constants for interacting with Spine models ## API ### spine.play_anim *Type:* FUNCTION Plays the specified animation on a Spine model. A [ref:spine_animation_done] message is sent to the callback (or message handler). Any spine events will also be handled in the same way. [icon:attention] The callback is not called (or message sent) if the animation is cancelled with [ref:spine.cancel]. The callback is called (or message sent) only for animations that play with the following playback modes * `go.PLAYBACK_ONCE_FORWARD` * `go.PLAYBACK_ONCE_BACKWARD` * `go.PLAYBACK_ONCE_PINGPONG` **Parameters** - `url` (string | hash | url) - The Spine model for which to play an animation - `anim_id` (string | hash) - Id of the animation to play - `playback` (number) - Playback mode of the animation (from go.PLAYBACK_*) - `options` (table) - Playback options - `blend_duration` (number) - Duration of a linear blend between the current and new animation. - `offset` (number) - The normalized initial value of the animation cursor when the animation starts playing. - `playback_rate` (constant) - The rate with which the animation will be played. Must be positive. - `track` (number) - The track index of the animation. Defaults to 1. Animations on different tracks play in parallel. - `mix_blend` (constant) - The mix blend mode for the animation (from spine.MIX_BLEND_*). Defaults to `spine.MIX_BLEND_REPLACE`. Ignored for animations on the first track. - `callback_function` (function) - function to call when the animation has completed or a Spine event occured - `self` (object) - The context of the calling script - `message_id` (hash) - The name of the message ("spine_animation_done" or "spine_event") - `message` (table) - A table that contains the response - `animation_id` (hash) - The animation that was completed - `track` (number) - The track index of the animation - `playback` (constant) - (spine_animation_done only!) The playback mode for the animation - `event_id` (hash) - (spine_event only!) the event that was triggered. - `t` (float) - (spine_event only!) the time at which the event occurred (seconds) - `integer` (int) - (spine_event only!) a custom integer associated with the event (0 by default). - `float` (float) - (spine_event only!) a custom float associated with the event (0 by default) - `string` (hash) - (spine_event only!) a custom string associated with the event (hash("") by default) - `sender` (url) - The invoker of the callback - the Spine model component ### spine.cancel *Type:* FUNCTION Cancels all running animations on a specified spine model component **Parameters** - `url` (string | hash | url) - The Spine model for which to cancel the animation - `options` (table) - Cancel options - `track` (number) - The index of the track which to cancel the animation on. Defaults to all animations on all tracks. ### spine.get_go *Type:* FUNCTION Returns the id of the game object that corresponds to a specified skeleton bone. **Parameters** - `url` (string | hash | url) - The Spine model to query - `bone_id` (hash) - Id of the corresponding bone ### spine.set_skin *Type:* FUNCTION Sets the spine skin on a spine model. **Parameters** - `url` (string | hash | url) - The Spine model to query - `skin` (string | hash) - Id of the corresponding skin ### spine.add_skin *Type:* FUNCTION Adds one spine skin on a spine model to another on the same model. **Parameters** - `url` (string | hash | url) - The Spine model to query - `skin_a` (string | hash) - Id of the corresponding skin that will recieve the added skin - `skin_b` (string | hash) - Id of the corresponding skin to add ### spine.copy_skin *Type:* FUNCTION Copies one spine skin on a spine model to another on the same model. **Parameters** - `url` (string | hash | url) - The Spine model to query - `skin_a` (string | hash) - Id of the corresponding skin that will recieve the copied skin - `skin_b` (string | hash) - Id of the corresponding skin to copy. ### spine.clear_skin *Type:* FUNCTION Clear all attachments and constraints from a skin on a spine model **Parameters** - `url` (string | hash | url) - The Spine model to query - `skin` (string | hash) - Id of the corresponding skin ### spine.set_attachment *Type:* FUNCTION Set the attachment of a slot on a spine model. **Parameters** - `url` (string | hash | url) - The Spine model to query - `slot` (string | hash) - Id of the slot - `attachment` (string | hash | nil) - Id of the attachment. May be nil to reset to default attachment. ### spine.set_slot_color *Type:* FUNCTION Set the color a slot will tint its attachments on a spine model. **Parameters** - `url` (string | hash | url) - The Spine model to query - `slot` (string | hash) - Id of the slot - `color` (vector4) - Tint applied to attachments in a slot ### spine.reset_constant *Type:* FUNCTION Resets a shader constant for a spine model component. (Previously set with `go.set()`) **Parameters** - `url` (string | hash | url) - The Spine model to query - `constant` (string | hash) - name of the constant ### spine.reset_ik_target *Type:* FUNCTION reset the IK constraint target position to default of a spinemodel. **Parameters** - `url` (string | hash | url) - The Spine model - `ik_constraint_id` (string | hash) - id of the corresponding IK constraint ### spine.set_ik_target_position *Type:* FUNCTION set the target position of an IK constraint object. **Parameters** - `url` (string | hash | url) - The Spine model - `ik_constraint_id` (string | hash) - id of the corresponding IK constraint - `position` (vector3) - target position ### spine.set_ik_target *Type:* FUNCTION set the IK constraint object target position to follow position. **Parameters** - `url` (string | hash | url) - The Spine model to query - `ik_constraint_id` (string | hash) - id of the corresponding IK constraint - `target_url` (string | hash | url) - target game object ### spine.physics_translate *Type:* FUNCTION Apply a physics-based translation to the Spine model. **Parameters** - `url` (string | hash | url) - The Spine model component to translate. - `translation` (vector3) - The translation vector to apply to the Spine model. ### spine.physics_rotate *Type:* FUNCTION Apply a physics-based rotation to the Spine model. **Parameters** - `url` (string | hash | url) - The Spine model component to rotate. - `center` (vector3) - The center point around which to rotate. - `degrees` (number) - The rotation angle in degrees. # extension-steam {#apis:extension-steam_steam} **Namespace:** `steam` **Language:** Lua **Type:** Extension Functions and constants for interacting with Steamworks. ## API ### steam.init *Type:* FUNCTION Initialize Steamworks. **Returns** - `boolean` - True if successful - `string` - Error message if unsuccessful. ### steam.update *Type:* FUNCTION Update Steamworks. Call this from a script component. ### steam.restart *Type:* FUNCTION Restart Steamworks. **Parameters** - `appid` (number) ### steam.final *Type:* FUNCTION Finalize Steamworks. ### EFloatingGamepadTextInputModeModeSingleLine *Type:* VARIABLE Enter dismisses the keyboard ### EFloatingGamepadTextInputModeModeMultipleLines *Type:* VARIABLE User needs to explicitly dismiss the keyboard ### EFloatingGamepadTextInputModeModeEmail *Type:* VARIABLE Keyboard is displayed in a special mode that makes it easier to enter emails ### EFloatingGamepadTextInputModeModeNumeric *Type:* VARIABLE Numeric keypad is shown ### EGamepadTextInputModeNormal *Type:* VARIABLE Normal text input ### EGamepadTextInputModePassword *Type:* VARIABLE Password text input ### EGamepadTextInputLineModeSingleLine *Type:* VARIABLE Single line text ### EGamepadTextInputLineModeMultipleLines *Type:* VARIABLE Multi line text ### ELeaderboardDataRequestGlobal *Type:* VARIABLE Requests rows in the leaderboard from the full table. ### ELeaderboardDataRequestGlobalAroundUser *Type:* VARIABLE Requests rows in the leaderboard from rows around the user. ### ELeaderboardDataRequestFriends *Type:* VARIABLE Requests all the rows for friends of the current user. ### ELeaderboardSortMethodNone *Type:* VARIABLE ### ELeaderboardSortMethodAscending *Type:* VARIABLE Top-score is lowest number. ### ELeaderboardSortMethodDescending *Type:* VARIABLE Top-score is highest number. ### ELeaderboardUploadScoreMethodNone *Type:* VARIABLE ### ELeaderboardUploadScoreMethodKeepBest *Type:* VARIABLE Leaderboard will keep user's best score. ### ELeaderboardUploadScoreMethodForceUpdate *Type:* VARIABLE Leaderboard will always replace score with specified. ### ELeaderboardDisplayTypeNone *Type:* VARIABLE ### ELeaderboardDisplayTypeNumeric *Type:* VARIABLE Simple numerical score. ### ELeaderboardDisplayTypeTimeSeconds *Type:* VARIABLE The score represents a time, in seconds. ### ELeaderboardDisplayTypeTimeMilliSeconds *Type:* VARIABLE The score represents a time, in milliseconds. ### EOverlayToStoreFlag_None *Type:* VARIABLE Passed as parameter to the store. ### EOverlayToStoreFlag_AddToCart *Type:* VARIABLE Passed as parameter to the store. ### EOverlayToStoreFlag_AddToCartAndShow *Type:* VARIABLE Passed as parameter to the store. ### EActivateGameOverlayToWebPageMode_Default *Type:* VARIABLE Passed as parameter to ActivateGameOverlayToWebPage. ### EActivateGameOverlayToWebPageMode_Modal *Type:* VARIABLE Passed as parameter to ActivateGameOverlayToWebPage. ### EPersonaStateOffline *Type:* VARIABLE Friend is not currently logged on. ### EPersonaStateOnline *Type:* VARIABLE Friend is logged on. ### EPersonaStateBusy *Type:* VARIABLE User is on, but busy. ### EPersonaStateAway *Type:* VARIABLE Auto-away feature. ### EPersonaStateSnooze *Type:* VARIABLE Auto-away for a long time. ### EPersonaStateLookingToTrade *Type:* VARIABLE Online, trading. ### EPersonaStateLookingToPlay *Type:* VARIABLE Online, wanting to play. ### EPersonaStateInvisible *Type:* VARIABLE Online, but appears offline to friends. This status is never published to clients. ### EFriendFlagNone *Type:* VARIABLE EFriendFlagNone ### EFriendFlagBlocked *Type:* VARIABLE EFriendFlagBlocked ### EFriendFlagFriendshipRequested *Type:* VARIABLE EFriendFlagFriendshipRequested ### EFriendFlagImmediate *Type:* VARIABLE EFriendFlagImmediate ### EFriendFlagClanMember *Type:* VARIABLE EFriendFlagClanMember ### EFriendFlagOnGameServer *Type:* VARIABLE EFriendFlagOnGameServer ### EFriendFlagRequestingFriendship *Type:* VARIABLE EFriendFlagRequestingFriendship ### EFriendFlagRequestingInfo *Type:* VARIABLE EFriendFlagRequestingInfo ### EFriendFlagIgnored *Type:* VARIABLE EFriendFlagIgnored ### EFriendFlagIgnoredFriend *Type:* VARIABLE EFriendFlagIgnoredFriend ### EFriendFlagChatMember *Type:* VARIABLE EFriendFlagChatMember ### EFriendFlagAll *Type:* VARIABLE EFriendFlagAll ### SteamNetworkingSend_Unreliable *Type:* VARIABLE SteamNetworkingSend_Unreliable ### SteamNetworkingSend_NoNagle *Type:* VARIABLE SteamNetworkingSend_NoNagle ### SteamNetworkingSend_UnreliableNoNagle *Type:* VARIABLE SteamNetworkingSend_UnreliableNoNagle ### SteamNetworkingSend_NoDelay *Type:* VARIABLE SteamNetworkingSend_NoDelay ### SteamNetworkingSend_UnreliableNoDelay *Type:* VARIABLE SteamNetworkingSend_UnreliableNoDelay ### SteamNetworkingSend_Reliable *Type:* VARIABLE SteamNetworkingSend_Reliable ### SteamNetworkingSend_ReliableNoNagle *Type:* VARIABLE SteamNetworkingSend_ReliableNoNagle ### SteamNetworkingSend_UseCurrentThread *Type:* VARIABLE SteamNetworkingSend_UseCurrentThread ### SteamNetworkingSend_AutoRestartBrokenSession *Type:* VARIABLE SteamNetworkingSend_AutoRestartBrokenSession ### ESteamNetConnectionEnd_Invalid *Type:* VARIABLE ESteamNetConnectionEnd_Invalid ### ESteamNetConnectionEnd_App_Generic *Type:* VARIABLE ESteamNetConnectionEnd_App_Generic ### ESteamNetConnectionEnd_AppException_Generic *Type:* VARIABLE ESteamNetConnectionEnd_AppException_Generic ### ESteamNetConnectionEnd_Local_OfflineMode *Type:* VARIABLE ESteamNetConnectionEnd_Local_OfflineMode ### ESteamNetConnectionEnd_Local_ManyRelayConnectivity *Type:* VARIABLE ESteamNetConnectionEnd_Local_ManyRelayConnectivity ### ESteamNetConnectionEnd_Local_HostedServerPrimaryRelay *Type:* VARIABLE ESteamNetConnectionEnd_Local_HostedServerPrimaryRelay ### ESteamNetConnectionEnd_Local_NetworkConfig *Type:* VARIABLE ESteamNetConnectionEnd_Local_NetworkConfig ### ESteamNetConnectionEnd_Local_Rights *Type:* VARIABLE ESteamNetConnectionEnd_Local_Rights ### ESteamNetConnectionEnd_Local_P2P_ICE_NoPublicAddresses *Type:* VARIABLE ESteamNetConnectionEnd_Local_P2P_ICE_NoPublicAddresses ### ESteamNetConnectionEnd_Remote_Timeout *Type:* VARIABLE ESteamNetConnectionEnd_Remote_Timeout ### ESteamNetConnectionEnd_Remote_BadCrypt *Type:* VARIABLE ESteamNetConnectionEnd_Remote_BadCrypt ### ESteamNetConnectionEnd_Remote_BadCert *Type:* VARIABLE ESteamNetConnectionEnd_Remote_BadCert ### ESteamNetConnectionEnd_Remote_BadProtocolVersion *Type:* VARIABLE ESteamNetConnectionEnd_Remote_BadProtocolVersion ### ESteamNetConnectionEnd_Remote_P2P_ICE_NoPublicAddresses *Type:* VARIABLE ESteamNetConnectionEnd_Remote_P2P_ICE_NoPublicAddresses ### ESteamNetConnectionEnd_Misc_Generic *Type:* VARIABLE ESteamNetConnectionEnd_Misc_Generic ### ESteamNetConnectionEnd_Misc_InternalError *Type:* VARIABLE ESteamNetConnectionEnd_Misc_InternalError ### ESteamNetConnectionEnd_Misc_Timeout *Type:* VARIABLE ESteamNetConnectionEnd_Misc_Timeout ### ESteamNetConnectionEnd_Misc_SteamConnectivity *Type:* VARIABLE ESteamNetConnectionEnd_Misc_SteamConnectivity ### ESteamNetConnectionEnd_Misc_NoRelaySessionsToClient *Type:* VARIABLE ESteamNetConnectionEnd_Misc_NoRelaySessionsToClient ### ESteamNetConnectionEnd_Misc_P2P_Rendezvous *Type:* VARIABLE ESteamNetConnectionEnd_Misc_P2P_Rendezvous ### ESteamNetConnectionEnd_Misc_P2P_NAT_Firewall *Type:* VARIABLE ESteamNetConnectionEnd_Misc_P2P_NAT_Firewall ### ESteamNetConnectionEnd_Misc_PeerSentNoConnection *Type:* VARIABLE ESteamNetConnectionEnd_Misc_PeerSentNoConnection ### ESteamNetworkingConnectionState_None *Type:* VARIABLE ESteamNetworkingConnectionState_None ### ESteamNetworkingConnectionState_Connecting *Type:* VARIABLE ESteamNetworkingConnectionState_Connecting ### ESteamNetworkingConnectionState_FindingRoute *Type:* VARIABLE ESteamNetworkingConnectionState_FindingRoute ### ESteamNetworkingConnectionState_Connected *Type:* VARIABLE ESteamNetworkingConnectionState_Connected ### ESteamNetworkingConnectionState_ClosedByPeer *Type:* VARIABLE ESteamNetworkingConnectionState_ClosedByPeer ### ESteamNetworkingConnectionState_ProblemDetectedLocally *Type:* VARIABLE ESteamNetworkingConnectionState_ProblemDetectedLocally ### ELobbyTypePrivate *Type:* VARIABLE ELobbyTypePrivate only way to join the lobby is to invite to someone else ### ELobbyTypeFriendsOnly *Type:* VARIABLE ELobbyTypeFriendsOnly shows for friends or invitees, but not in lobby list ### ELobbyTypePublic *Type:* VARIABLE ELobbyTypePublic visible for friends and in lobby list ### ELobbyTypeInvisible *Type:* VARIABLE ELobbyTypeInvisible returned by search, but not visible to other friends ### ELobbyTypePrivateUnique *Type:* VARIABLE ELobbyTypePrivateUnique private, unique and does not delete when empty ### EAuthSessionResponseOK *Type:* VARIABLE EAuthSessionResponseOK Steam has verified the user is online, the ticket is valid and ticket has not been reused. ### EAuthSessionResponseUserNotConnectedToSteam *Type:* VARIABLE EAuthSessionResponseUserNotConnectedToSteam The user in question is not connected to steam. ### EAuthSessionResponseNoLicenseOrExpired *Type:* VARIABLE EAuthSessionResponseNoLicenseOrExpired The user doesn't have a license for this App ID or the ticket has expired. ### EAuthSessionResponseVACBanned *Type:* VARIABLE EAuthSessionResponseVACBanned The user is VAC banned for this game. ### EAuthSessionResponseLoggedInElseWhere *Type:* VARIABLE EAuthSessionResponseLoggedInElseWhere The user account has logged in elsewhere and the session containing the game instance has been disconnected. ### EAuthSessionResponseVACCheckTimedOut *Type:* VARIABLE EAuthSessionResponseVACCheckTimedOut VAC has been unable to perform anti-cheat checks on this user. ### EAuthSessionResponseAuthTicketCanceled *Type:* VARIABLE EAuthSessionResponseAuthTicketCanceled The ticket has been canceled by the issuer. ### EAuthSessionResponseAuthTicketInvalidAlreadyUsed *Type:* VARIABLE EAuthSessionResponseAuthTicketInvalidAlreadyUsed This ticket has already been used, it is not valid. ### EAuthSessionResponseAuthTicketInvalid *Type:* VARIABLE EAuthSessionResponseAuthTicketInvalid This ticket is not from a user instance currently connected to steam. ### EAuthSessionResponsePublisherIssuedBan *Type:* VARIABLE EAuthSessionResponsePublisherIssuedBan The user is banned for this game. The ban came via the web api and not VAC. ### EAuthSessionResponseAuthTicketNetworkIdentityFailure *Type:* VARIABLE EAuthSessionResponseAuthTicketNetworkIdentityFailure The network identity in the ticket does not match the server authenticating the ticket. ### steam.apps_is_dlc_installed *Type:* FUNCTION Takes AppID of DLC and checks if the user owns the DLC & if the DLC is installed. **Parameters** - `app_id` (number) **Returns** - `boolean` ### steam.apps_get_current_game_language *Type:* FUNCTION Gets the current game language. **Returns** - `string` ### steam.friends_get_friend_persona_name *Type:* FUNCTION Returns the name of another user. Same rules as GetFriendPersonaState() apply as to whether or not the user knowns the name of the other user note that on first joining a lobby, chat room or game server the local user will not known the name of the other users automatically; that information will arrive asyncronously. **Parameters** - `steamIDFriend` (string) **Returns** - `string` - Name of user ### steam.friends_get_persona_name *Type:* FUNCTION Returns the local players name - guaranteed to not be NULL. This is the same name as on the users community profile page. This is stored in UTF-8 format. **Returns** - `string` - Name of user ### steam.friends_get_persona_state *Type:* FUNCTION Gets the status of the current user. Returned as EPersonaState. **Returns** - `number` - Status of user. ### steam.friends_get_friend_count *Type:* FUNCTION Friend iteration. Takes a set of EFriendFlags, and returns the number of users the client knows about who meet that criteria. Then GetFriendByIndex() can then be used to return the id's of each of those users. **Parameters** - `iFriendFlags` (number) - Set of friend flags to match friends against. **Returns** - `number` - Number of users matching search. ### steam.friends_get_friend_by_index *Type:* FUNCTION Returns the steamID of a user. The returned CSteamID can then be used by all the functions below to access details about the user. **Parameters** - `iFriend` (number) - Is a index of range [0, GetFriendCount()) - `iFriendsFlags` (number) - Must be the same value as used in GetFriendCount() **Returns** - `string` - Steam id of the user ### steam.friends_get_friend_persona_state *Type:* FUNCTION Returns the current status of the specified user. This will only be known by the local user if steamIDFriend is in their friends list; on the same game server; in a chat room or lobby; or in a small group with the local user. **Parameters** - `steamIDFriend` (string) - Id of friend **Returns** - `number` - State of friend ### steam.friends_get_friend_steam_level *Type:* FUNCTION Get friends steam level. **Parameters** - `steamIDFriend` (string) - Id of friend **Returns** - `number` - Steam level of friend ### steam.friends_get_friend_relationship *Type:* FUNCTION Returns a relationship to a user. **Parameters** - `steamIDFriend` (string) - Id of friend **Returns** - `number` - Relationship to the user. ### steam.friends_get_small_friend_avatar *Type:* FUNCTION Gets a handle to the small (32*32px) avatar for the specified user. This is a handle to be used in IClientUtils::GetImageRGBA(), or 0 if none set **Parameters** - `steamIDFriend` (string) - Id of friend **Returns** - `number` - Image handle. ### steam.friends_get_medium_friend_avatar *Type:* FUNCTION Gets a handle to the medium (64*64px) avatar for the specified user. This is a handle to be used in IClientUtils::GetImageRGBA(), or 0 if none set **Parameters** - `steamIDFriend` (string) - Id of friend **Returns** - `number` - Image handle. ### steam.friends_get_large_friend_avatar *Type:* FUNCTION Gets a handle to the large (128*128px) avatar for the specified user. This is a handle to be used in IClientUtils::GetImageRGBA(), or 0 if none set **Parameters** - `steamIDFriend` (string) - Id of friend **Returns** - `number` - Image handle. ### steam.friends_activate_game_overlay_to_store *Type:* FUNCTION Activates game overlay to store page for app. **Parameters** - `app_id` (number) - `flag` (number) - EOverlayToStoreFlag ### steam.friends_activate_game_overlay_to_web_page *Type:* FUNCTION Activates game overlay web browser directly to the specified URL. Full address with protocol type is required, e.g. http://www.steamgames.com/ **Parameters** - `url` (string) - `mode` (number) - EActivateGameOverlayToWebPageMode ### steam.friends_set_rich_presence *Type:* FUNCTION Sets a Rich Presence key/value for the current user. **Parameters** - `key` (string) - `value` (string) **Returns** - `boolean` - True if the rich presence was set successfully, otherwise False. ### steam.friends_clear_rich_presence *Type:* FUNCTION Clears all of the current user's Rich Presence key/values. ### steam.friends_invite_user_to_game *Type:* FUNCTION Invites a friend or clan member to the current game using a special invite string. If the target accepts the invite, a GameRichPresenceJoinRequested_t callback is posted containing the connect string. **Parameters** - `steamIDFriend` (string) - Id of friend - `connect` (string) - String **Returns** - `boolean` ### steam.set_listener *Type:* FUNCTION Set a listener. **Parameters** - `listener` (function) - Listener function to call ### steam.matchmaking_add_request_lobby_list_string_filter *Type:* FUNCTION Adds a string comparison filter to the next RequestLobbyList call. **Parameters** - `key` (string) - `value` (number) - `cmp` (number) ### steam.matchmaking_add_request_lobby_list_numerical_filter *Type:* FUNCTION Adds a numerical comparison filter to the next RequestLobbyList call. **Parameters** - `key` (string) - `value` (number) - `cmp` (number) ### steam.matchmaking_add_request_lobby_list_near_value_filter *Type:* FUNCTION Sorts the results closest to the specified value. **Parameters** - `key` (string) - `value` (number) ### steam.matchmaking_add_request_lobby_list_filter_slots_available *Type:* FUNCTION Filters to only return lobbies with the specified number of open slots. Available. **Parameters** - `slots` (number) ### steam.matchmaking_add_request_lobby_list_distance_filter *Type:* FUNCTION Sets the physical distance for which we should search for lobbies, this is. Based on the users IP address and a IP location map on the Steam backed. **Parameters** - `dist` (number) ### steam.matchmaking_add_request_lobby_list_result_count_filter *Type:* FUNCTION Sets the maximum number of lobbies to return. The lower the count the faster. It is to download the lobby results & details to the client. **Parameters** - `max_count` (number) ### steam.matchmaking_add_request_lobby_list_compatible_members_filter *Type:* FUNCTION Unused - Checks the player compatibility based on the frenemy system. **Parameters** - `steam_id` (string) ### steam.matchmaking_request_lobby_list *Type:* FUNCTION Get a filtered list of relevant lobbies. Will return results as a LobbyMatchList_t event **Returns** - `string` - Callback id ### steam.matchmaking_get_lobby_by_index *Type:* FUNCTION Gets the Steam ID of the lobby at the specified index. This should only be called after a LobbyMatchList_t call result is received **Parameters** - `index` (number) - The index of the lobby to get the Steam ID of, from 0 to LobbyMatchList_t.m_nLobbiesMatching **Returns** - `string` - Id of lobby ### steam.matchmaking_create_lobby *Type:* FUNCTION Create a new matchmaking lobby. Will generate a LobbyCreated_t, LobbyEnter_t and LobbyDataUpdate_t event **Parameters** - `lobby_type` (number) - The type and visibility of this lobby. - `max_members` (number) - The maximum number of players that can join this lobby. **Returns** - `string` - Callback id ### steam.matchmaking_join_lobby *Type:* FUNCTION Joins an existing lobby. Will generate a LobbyEnter_t event **Parameters** - `lobby_id` (string) - The Steam ID of the lobby to join. **Returns** - `string` - Callback id ### steam.matchmaking_leave_lobby *Type:* FUNCTION Leave a lobby that the user is currently in. Leave a lobby that the user is currently in; this will take effect immediately on the client side, other users in the lobby will be notified by a LobbyChatUpdate_t callback. **Parameters** - `lobby_id` (string) - The lobby to leave ### steam.matchmaking_get_lobby_owner *Type:* FUNCTION Returns the current lobby owner. There always one lobby owner - if the current owner leaves, another user in the lobby will become the owner automatically. It is possible (but rare) to join a lobby just as the owner is leaving, thus entering a lobby with self as the owner. You must be a member of the lobby to access this. **Parameters** - `lobby_id` (string) - The Steam ID of the lobby to get the owner of. **Returns** - `string` - Id of owner ### steam.matchmaking_set_lobby_owner *Type:* FUNCTION Changes who the lobby owner is. This can only be set by the owner of the lobby. This will trigger a LobbyDataUpdate_t for all of the users in the lobby, each user should update their local state to reflect the new owner. This is typically accomplished by displaying a crown icon next to the owners name. **Parameters** - `lobby_id` (string) - The Steam ID of the lobby to get the owner of. - `new_owner` (string) - The new owner ### steam.matchmaking_set_lobby_type *Type:* FUNCTION Updates what type of lobby this is. This is also set when you create the lobby with CreateLobby. This can only be set by the owner of the lobby. **Parameters** - `lobby_id` (string) - The Steam ID of the lobby - `type` (number) - The lobby type ### steam.matchmaking_set_lobby_joinable *Type:* FUNCTION Sets whether or not a lobby is joinable by other players. This always defaults to enabled for a new lobby. If joining is disabled, then no players can join, even if they are a friend or have been invited. Lobbies with joining disabled will not be returned from a lobby search. **Parameters** - `lobby_id` (string) - The Steam ID of the lobby - `joinable` (boolean) - Enable or disable allowing users to join this lobby? **Returns** - `boolean` - Success ### steam.matchmaking_set_lobby_member_limit *Type:* FUNCTION Set the maximum number of players that can join the lobby. This is also set when you create the lobby with CreateLobby. This can only be set by the owner of the lobby. **Parameters** - `lobby_id` (string) - The Steam ID of the lobby to set the member limit for. - `max_members` (number) - The maximum number of players allowed in this lobby. This can not be above 250. **Returns** - `boolean` - Success ### steam.matchmaking_get_lobby_member_limit *Type:* FUNCTION The current limit on the **Parameters** - `lobby_id` (string) - The Steam ID of the lobby to get the member limit of. **Returns** - `number` - The current limit ### steam.matchmaking_get_num_lobby_members *Type:* FUNCTION Gets the number of users in a lobby. This is used for iteration, after calling this then GetLobbyMemberByIndex can be used to get the Steam ID of each person in the lobby. Persona information for other lobby members (name, avatar, etc.) is automatically received and accessible via the ISteamFriends interface. The current user must be in the lobby to retrieve the Steam IDs of other users in that lobby. **Parameters** - `lobby_id` (string) - The Steam ID of the lobby to get the owner of. **Returns** - `number` - Number of users in the lobby ### steam.matchmaking_get_lobby_member_by_index *Type:* FUNCTION Gets the Steam ID of the lobby member at the given index. You must call matchmaking_get_num_lobby_members before calling this. The current user must be in the lobby to retrieve the Steam IDs of other users in that lobby. **Parameters** - `lobby_id` (string) - `index` (number) **Returns** - `string` - Id of member ### steam.matchmaking_set_lobby_data *Type:* FUNCTION Sets a key/value pair in the lobby metadata. **Parameters** - `lobby_id` (string) - `key` (string) - `data` (string) **Returns** - `boolean` ### steam.matchmaking_set_lobby_member_data *Type:* FUNCTION Sets per-user metadata for the local user. **Parameters** - `lobby_id` (string) - `key` (string) - `data` (string) ### steam.matchmaking_get_lobby_data *Type:* FUNCTION Get data associated with this lobby. **Parameters** - `lobby_id` (string) - `key` (string) **Returns** - `string` - Data ### steam.matchmaking_get_lobby_member_data *Type:* FUNCTION Gets per-user metadata from another player in the specified lobby. **Parameters** - `lobby_id` (string) - `user_id` (string) - `key` (string) **Returns** - `string` - Data ### steam.matchmaking_get_lobby_data_count *Type:* FUNCTION Returns the number of metadata keys set on the specified lobby. **Parameters** - `lobby_id` (string) **Returns** - `number` - Number of keys ### steam.matchmaking_get_lobby_data_by_index *Type:* FUNCTION Returns a lobby metadata key/values pair by index. **Parameters** - `lobby_id` (string) - `index` (number) **Returns** - `boolean` - `string` - `string` ### steam.matchmaking_send_lobby_chat_message *Type:* FUNCTION Broadcasts a chat message to the all the users in the lobby. **Parameters** - `lobby_id` (string) - `body` (string) **Returns** - `boolean` ### steam.matchmaking_get_lobby_chat_entry *Type:* FUNCTION Get a chat message as specified in a LobbyChatMsg_t callback. **Parameters** - `lobby_id` (string) - `index` (number) **Returns** - `string` - `string` - `number` ### steam.networking_send_message_to_user *Type:* FUNCTION Send message. **Parameters** - `identity_remote` (string) - `data` (string) - `send_flags` (number) - A bitmask of k_nSteamNetworkingSend_xxx options - `remote_channel` (number) - A routing number you can use to help route message to different systems ### steam.networking_receive_messages_on_channel *Type:* FUNCTION Receive message. **Parameters** - `localChannel` (number) **Returns** - `table` ### steam.networking_accept_session_with_user *Type:* FUNCTION Accept session. Call this in response to a SteamNetworkingMessagesSessionRequest_t callback. **Parameters** - `identity_remote` (string) **Returns** - `boolean` - Returns false if there is no session with the user pending or otherwise. If there is an existing active session, this function will return true, even if it is not pending. ### steam.networking_close_session_with_user *Type:* FUNCTION Close sesssion. Call this when you're done talking to a user to immediately free up resources under-the-hood **Parameters** - `identity_remote` (string) **Returns** - `boolean` ### steam.networking_close_channel_with_user *Type:* FUNCTION Close channel. Call this when you're done talking to a user on a specific channel. **Parameters** - `identity_remote` (string) - `local_channel` (number) **Returns** - `boolean` ### steam.networking_get_session_connection_info *Type:* FUNCTION Get connection info. Returns information about the latest state of a connection, if any, with the given peer. **Parameters** - `identity_remote` (string) **Returns** - `table` - Connection info (state, info, status) ### steam.remote_storage_file_share *Type:* FUNCTION Share a file. **Parameters** - `filename` (string) - Name of file to share **Returns** - `string` ### steam.remote_storage_get_file_count *Type:* FUNCTION Get number of uploaded files. **Returns** - `number` - File count ### steam.remote_storage_get_file_name_and_size *Type:* FUNCTION Get file information. **Returns** - `number` - File count ### steam.remote_storage_get_quota *Type:* FUNCTION Get storage quota. **Returns** - `number` - Available bytes - `number` - Total bytes ### steam.remote_storage_file_write *Type:* FUNCTION Creates a new file, writes the bytes to the file, and then closes the file. If the target file already exists, it is overwritten. **Parameters** - `filename` (string) - The name of the file to write to. - `data` (string) **Returns** - `boolean` - Success ### steam.remote_storage_file_read *Type:* FUNCTION Opens a binary file, reads the contents of the file into a byte array,. And then closes the file. **Parameters** - `filename` (string) - Name of the file to read from **Returns** - `string` ### steam.user_get_steam_id *Type:* FUNCTION Returns the CSteamID of the account currently logged into the Steam client. A CSteamID is a unique identifier for an account, and used to differentiate users in all parts of the Steamworks API. **Returns** - `string` ### steam.user_get_player_steam_level *Type:* FUNCTION Gets the Steam Level of the user, as shown on their profile. **Returns** - `number` ### steam.user_get_game_badge_level *Type:* FUNCTION Trading Card badges data access. If you only have one set of cards, the series will be 1. The user has can have two different badges for a series; the regular (max level 5) and the foil (max level 1). **Returns** - `number` - `boolean` ### steam.user_logged_on *Type:* FUNCTION Returns true if the Steam client current has a live connection to the Steam. Servers. **Returns** - `boolean` ### steam.user_is_behind_nat *Type:* FUNCTION Returns true if this users looks like they are behind a NAT device. Only valid once the user has connected to steam . **Returns** - `boolean` ### steam.user_is_phone_verified *Type:* FUNCTION Gets whether the users phone number is verified. **Returns** - `boolean` ### steam.user_is_phone_identifying *Type:* FUNCTION Gets whether the users phone number is identifying. **Returns** - `boolean` ### steam.user_is_phone_requiring_verification *Type:* FUNCTION Gets whether the users phone number is awaiting (re)verification. **Returns** - `boolean` ### steam.user_is_two_factor_enabled *Type:* FUNCTION Gets whether the user has two factor enabled on their account. **Returns** - `boolean` ### steam.user_get_auth_session_ticket *Type:* FUNCTION Get an authentication ticket. Retrieve an authentication ticket to be sent to the entity who wishes to authenticate you. **Returns** - `string` - Auth ticket or null - `number` - Ticket handle or null - `string` - Error message or null ### steam.user_begin_auth_session *Type:* FUNCTION Validate an authentication ticket. Authenticate the ticket from the entity Steam ID to be sure it is valid and isn't reused. Note that identity is not confirmed until the callback ValidateAuthTicketResponse_t is received and the return value in that callback is checked for success. **Parameters** - `ticket` (string) - The auth ticket to validate - `steamId` (string) - The entity's Steam ID that sent this ticket. **Returns** - `number` ### steam.user_cancel_auth_ticket *Type:* FUNCTION Cancels an auth ticket. Cancels an auth ticket received from GetAuthSessionTicket or GetAuthTicketForWebApi. This should be called when no longer playing with the specified entity. **Parameters** - `ticket` (number) - The active auth ticket to cancel. ### steam.user_end_auth_session *Type:* FUNCTION Ends an auth session. Ends an auth session that was started with BeginAuthSession. This should be called when no longer playing with the specified entity. **Parameters** - `steamId` (string) - The entity to end the active auth session with. ### steam.user_get_auth_ticket_for_web_api *Type:* FUNCTION Get an authentication ticket for web API. Request an authentication ticket suitable to authenticated in a web backend. Will trigger a GetTicketForWebApiResponse_t callback when the ticket is ready. **Parameters** - `identity` (string) - Optional identity string to associate with the ticket **Returns** - `number` - The handle of the requested ticket - `string` - Error message or null ### steam.user_stats_get_stat_int *Type:* FUNCTION Get user stat as an integer. Https://partner.steamgames.com/doc/api/ISteamUserStats#GetStat **Parameters** - `id` (string) - Id of the stat to get **Returns** - `boolean` - `number` - The stat or nil ### steam.user_stats_set_stat_int *Type:* FUNCTION Set user stat. Https://partner.steamgames.com/doc/api/ISteamUserStats#SetStat **Parameters** - `id` (string) - Id of the stat to set - `stat` (number) - Number to set **Returns** - `boolean` ### steam.user_stats_get_stat_float *Type:* FUNCTION Get user stat as a floating point number. Https://partner.steamgames.com/doc/api/ISteamUserStats#GetStat **Parameters** - `id` (string) - Id of the stat to get **Returns** - `boolean` - `number` - The stat ### steam.user_stats_set_stat_float *Type:* FUNCTION Set user stat. Https://partner.steamgames.com/doc/api/ISteamUserStats#SetStat **Parameters** - `id` (string) - Id of the stat to set - `stat` (number) - Number to set **Returns** - `boolean` ### steam.user_stats_request_global_stats *Type:* FUNCTION Requests global stats data, which is available for stats marked as "aggregated". This call is asynchronous, with the results returned in GlobalStatsReceived_t. nHistoryDays specifies how many days of day-by-day history to retrieve in addition to the overall totals. The limit is 60. https://partner.steamgames.com/doc/api/ISteamUserStats#RequestGlobalStats **Parameters** - `history_days` (number) **Returns** - `boolean` ### steam.user_stats_store_stats *Type:* FUNCTION Store the current data on the server. Will get a callback when set and one callback for every new achievement If the callback has a result of k_EResultInvalidParam, one or more stats uploaded has been rejected, either because they broke constraints or were out of date. In this case the server sends back updated values. The stats should be re-iterated to keep in sync. https://partner.steamgames.com/doc/api/ISteamUserStats#StoreStats **Returns** - `boolean` ### steam.user_stats_reset_all_stats *Type:* FUNCTION Reset stats. Https://partner.steamgames.com/doc/api/ISteamUserStats#ResetAllStats **Parameters** - `achievements` (boolean) - True if achievements should be reset as well. **Returns** - `boolean` ### steam.user_stats_set_achievement *Type:* FUNCTION Set achievement. Https://partner.steamgames.com/doc/api/ISteamUserStats#SetAchievement **Parameters** - `name` (string) **Returns** - `boolean` ### steam.user_stats_get_achievement *Type:* FUNCTION Get achievement. Https://partner.steamgames.com/doc/api/ISteamUserStats#GetAchievement **Parameters** - `name` (string) **Returns** - `boolean` - `boolean` ### steam.user_stats_clear_achievement *Type:* FUNCTION Clear achievement. Https://partner.steamgames.com/doc/api/ISteamUserStats#ClearAchievement **Parameters** - `name` (string) **Returns** - `boolean` ### steam.user_stats_get_num_achievements *Type:* FUNCTION Used for iterating achievements. In general games should not need these functions because they should have a list of existing achievements compiled into them. https://partner.steamgames.com/doc/api/ISteamUserStats#GetNumAchievements **Returns** - `number` - Number of achievements. ### steam.user_stats_get_achievement_name *Type:* FUNCTION Get achievement name iAchievement in [0,GetNumAchievements). Https://partner.steamgames.com/doc/api/ISteamUserStats#GetAchievementName **Parameters** - `index` (number) **Returns** - `string` ### steam.user_stats_get_achievement_display_attribute *Type:* FUNCTION Get general attributes for an achievement. Accepts the following keys * "name" and "desc" for retrieving the localized achievement name and description (returned in UTF8) * "hidden" for retrieving if an achievement is hidden (returns "0" when not hidden, "1" when hidden) https://partner.steamgames.com/doc/api/ISteamUserStats#GetAchievementDisplayAttribute **Parameters** - `name` (string) - `key` (string) - Either "name", "desc" or "hidden" **Returns** - `string` ### steam.user_stats_get_achievement_achieved_percent *Type:* FUNCTION Returns the percentage of users who have achieved the specified achievement. Https://partner.steamgames.com/doc/api/ISteamUserStats#GetAchievementAchievedPercent **Returns** - `boolean` - `number` ### steam.user_stats_find_leaderboard *Type:* FUNCTION Find a leaderboard. Will return leaderboard asynchronously. https://partner.steamgames.com/doc/api/ISteamUserStats#FindLeaderboard **Parameters** - `name` (string) ### steam.user_stats_find_or_create_leaderboard *Type:* FUNCTION Gets a leaderboard by name, it will create it if it's not yet created. This call is asynchronous, with the result returned in a listener callback with event set to LeaderboardFindResult_t. https://partner.steamgames.com/doc/api/ISteamUserStats#FindOrCreateLeaderboard **Parameters** - `leaderboard_name` (string) - The name of the leaderboard to find or create. - `eLeaderboardSortMethod` (ELeaderboardSortMethod) - The sort order of the new leaderboard if it's created. - `eLeaderboardDisplayType` (ELeaderboardDisplayType) - The display type (used by the Steam Community web site) of the new leaderboard if it's created. ### steam.user_stats_get_leaderboard_name *Type:* FUNCTION Get the name of a leaderboard. Https://partner.steamgames.com/doc/api/ISteamUserStats#GetLeaderboardName **Parameters** - `leaderboard` (string) **Returns** - `string` ### steam.user_stats_get_leaderboard_entry_count *Type:* FUNCTION Get the total number of entries in a leaderboard, as of the last request. Https://partner.steamgames.com/doc/api/ISteamUserStats#GetLeaderboardEntryCount **Parameters** - `leaderboard` (string) **Returns** - `number` ### steam.user_stats_get_leaderboard_sort_method *Type:* FUNCTION Returns the sort method of the leaderboard. Https://partner.steamgames.com/doc/api/ISteamUserStats#GetLeaderboardSortMethod **Parameters** - `leaderboard` (string) **Returns** - `number` ### steam.user_stats_get_leaderboard_display_type *Type:* FUNCTION Returns the display type of a leaderboard handle. Https://partner.steamgames.com/doc/api/ISteamUserStats#GetLeaderboardDisplayType **Parameters** - `leaderboard` (string) **Returns** - `number` ### steam.user_stats_download_leaderboard_entries *Type:* FUNCTION Asks the Steam back-end for a set of rows in the leaderboard. This call is asynchronous, with the result returned in a listener callback with event set to LeaderboardScoresDownloaded_t. LeaderboardScoresDownloaded_t will contain a handle to pull the results from GetDownloadedLeaderboardEntries(). You can ask for more entries than exist, and it will return as many as do exist. * k_ELeaderboardDataRequestGlobal requests rows in the leaderboard from the full table, with nRangeStart & nRangeEnd in the range [1, TotalEntries] * k_ELeaderboardDataRequestGlobalAroundUser requests rows around the current user, nRangeStart being negate e.g. DownloadLeaderboardEntries( hLeaderboard, k_ELeaderboardDataRequestGlobalAroundUser, -3, 3 ) will return 7 rows, 3 before the user, 3 after * k_ELeaderboardDataRequestFriends requests all the rows for friends of the current user https://partner.steamgames.com/doc/api/ISteamUserStats#DownloadLeaderboardEntries **Parameters** - `leaderboard` (string) - `request` (ELeaderboardDataRequest) - `start` (number) - `end` (number) ### steam.user_stats_get_downloaded_leaderboard_entry *Type:* FUNCTION Returns data about a single leaderboard entry. Https://partner.steamgames.com/doc/api/ISteamUserStats#GetDownloadedLeaderboardEntry **Parameters** - `hSteamLeaderboardEntries` (string) - Leaderboard entries handle - `index` (number) - Which entry to get **Returns** - `boolean` - `table` - The requested leaderboard entry. ### steam.user_stats_upload_leaderboard_score *Type:* FUNCTION Uploads a user score to a specified leaderboard. This call is asynchronous, with the result returned in a listener callback with event set to LeaderboardScoreUploaded_t. https://partner.steamgames.com/doc/api/ISteamUserStats#UploadLeaderboardScore **Parameters** - `leaderboard` (string) - `eLeaderboardUploadScoreMethod` (ELeaderboardUploadScoreMethod) - `nScore` (number) ### steam.user_stats_attach_leadboard_ugc *Type:* FUNCTION Attaches a piece of user generated content the current user's entry on a. Leaderboard. https://partner.steamgames.com/doc/api/ISteamUserStats#AttachLeaderboardUGC **Parameters** - `leaderboard` (string) - `ugc_handle` (string) **Returns** - `string` - API call id ### steam.utils_get_app_id *Type:* FUNCTION Returns the appID of the current process. **Returns** - `number` ### steam.utils_get_seconds_since_app_active *Type:* FUNCTION Return the number of seconds since the user. **Returns** - `number` ### steam.utils_is_steam_running_on_steam_deck *Type:* FUNCTION Returns true if currently running on the Steam Deck device. **Returns** - `boolean` ### steam.utils_is_steam_overlay_available *Type:* FUNCTION Returns true if the Steam Overlay is running and the user can access it. **Returns** - `boolean` ### steam.utils_get_image_size *Type:* FUNCTION Get size of image. **Parameters** - `image` (number) - Image handle **Returns** - `boolean` - True if size of image was read successfully - `number` - Image width or nil - `number` - Image height or nil ### steam.utils_get_image_rgba *Type:* FUNCTION Get image in RGBA format. **Parameters** - `image` (number) - Image handle - `size` (number) - Size of image **Returns** - `boolean` - True if size of image was read successfully - `string` ### steam.utils_get_server_real_time *Type:* FUNCTION Returns the Steam server time in Unix epoch format. (Number of seconds since Jan 1, 1970 UTC). **Returns** - `number` - Time ### steam.utils_show_floating_gamepad_text_input *Type:* FUNCTION Opens a floating keyboard over the game content and sends OS keyboard keys directly to the game. **Parameters** - `mode` (number) - EFloatingGamepadTextInputMode - `x` (number) - Text field x position - `y` (number) - Text field y position - `width` (number) - Text field width - `height` (number) - Text field height **Returns** - `boolean` - True if the floating keyboard was shown, otherwise, false. ### steam.utils_show_gamepad_text_input *Type:* FUNCTION Activates the Big Picture text input dialog which only supports gamepad input. **Parameters** - `input_mode` (number) - EGamepadTextInputMode - `line_input_mode` (number) - EGamepadTextInputLineMode - `description` (string) - Sets the description that should inform the user what the input dialog is for - `existing_text` (string) - Sets the preexisting text which the user can edit. **Returns** - `boolean` - True if the big picture overlay is running; otherwise, false # extension-websocket {#apis:extension-websocket_websocket} **Namespace:** `websocket` **Language:** Lua **Type:** Extension Functions and constants for using websockets. Supported on all platforms. ## API ### websocket.connect *Type:* FUNCTION Connects to a remote address **Parameters** - `url` (string) - url of the remote connection - `params` (table) - optional parameters as properties. The following parameters can be set - `timeout` (number) - Timeout for the connection sequence (milliseconds). Not used on HTML5. (Default is 3000) - `protocol` (string) - the protocol to use (e.g. 'chat'). If not set, no `Sec-WebSocket-Protocol` header is sent. - `headers` (string) - list of http headers. Each pair is separated with "\r\n". Not used on HTML5. - `callback` (function) - callback that receives all messages from the connection - `self` (object) - The script instance that was used to register the callback - `connection` (object) - the connection - `data` (table) - the event payload - `event` (number) - The current event. One of the following - `websocket.EVENT_CONNECTED` - `websocket.EVENT_DISCONNECTED` - `websocket.EVENT_ERROR` - `websocket.EVENT_MESSAGE` - `message` (string) - The received data if event is `websocket.EVENT_MESSAGE`. Error message otherwise - `handshake_response` (table) - Handshake response information (status, headers etc) - `code` (number) - Status code received from the server if the server closed the connection. Only present if event is `EVENT_DISCONNECTED`. **Returns** - `object` - the connection **Examples** ``` local function websocket_callback(self, conn, data) if data.event == websocket.EVENT_DISCONNECTED then log("Disconnected: " .. tostring(conn)) self.connection = nil update_gui(self) elseif data.event == websocket.EVENT_CONNECTED then update_gui(self) log("Connected: " .. tostring(conn)) elseif data.event == websocket.EVENT_ERROR then log("Error: '" .. data.message .. "'") elseif data.event == websocket.EVENT_MESSAGE then log("Receiving: '" .. tostring(data.message) .. "'") end end function init(self) self.url = "ws://echo.websocket.events" local params = { timeout = 3000, headers = "Sec-WebSocket-Protocol: chat\r\nOrigin: mydomain.com\r\n" } self.connection = websocket.connect(self.url, params, websocket_callback) end function finalize(self) if self.connection ~= nil then websocket.disconnect(self.connection) end end ``` ### websocket.disconnect *Type:* FUNCTION Explicitly close a websocket **Parameters** - `connection` (object) - the websocket connection ### websocket.send *Type:* FUNCTION Send data on a websocket **Parameters** - `connection` (object) - the websocket connection - `message` (string) - the message to send - `options` (table) - options for this particular message. May be `nil` - `type` (number) - The data type of the message - `websocket.DATA_TYPE_BINARY` (default) - `websocket.DATA_TYPE_TEXT` **Examples** ``` local function websocket_callback(self, conn, data) if data.event == websocket.EVENT_CONNECTED then websocket.send(conn, "Hello from the other side") end end function init(self) self.url = "ws://echo.websocket.org" local params = {} self.connection = websocket.connect(self.url, params, websocket_callback) end ``` ### EVENT_CONNECTED *Type:* VARIABLE The websocket was connected ### EVENT_DISCONNECTED *Type:* VARIABLE The websocket disconnected ### EVENT_MESSAGE *Type:* VARIABLE The websocket received data ### EVENT_ERROR *Type:* VARIABLE The websocket encountered an error # extension-webview {#apis:extension-webview_webview} **Namespace:** `webview` **Language:** Lua **Type:** Extension Functions and constants for interacting with webview APIs ## API ### webview.create *Type:* FUNCTION Creates a webview instance. It can show HTML pages as well as evaluate Javascript. The view remains hidden until the first call. There can exist a maximum of 4 webviews at the same time. On iOS, the callback will never get a `webview.CALLBACK_RESULT_EVAL_ERROR`, due to the iOS SDK implementation." **Parameters** - `callback` (function) - A callback which receives info about finished requests taking the following parameters: - `self` (object) - The calling script - `webview_id` (number) - The webview id - `request_id` (number) - The request id - `type` (enum) - The type of callback - `webview.CALLBACK_RESULT_URL_OK` - `webview.CALLBACK_RESULT_URL_ERROR` - `webview.CALLBACK_RESULT_URL_LOADING` - `webview.CALLBACK_RESULT_EVAL_OK` - `webview.CALLBACK_RESULT_EVAL_ERROR` - `data` (table) - A table holding the data - `url` (string) - The url used in the `webview.open()` call. `nil` otherwise. - `result` (string) - Holds the result of either: a failed url open, a successful eval request or a failed eval. `nil` otherwise. **Examples** ``` local function webview_callback(self, webview_id, request_id, type, data) if type == webview.CALLBACK_RESULT_URL_OK then -- the page is now loaded, let's show it webview.set_visible(webview_id, 1) elseif type == webview.CALLBACK_RESULT_URL_ERROR then print("Failed to load url: " .. data["url"]) print("Error: " .. data["error"]) elseif type == webview.CALLBACK_RESULT_URL_LOADING then -- a page is loading -- return false to prevent it from loading -- return true or nil to continue loading the page if data.url ~= "https://www.defold.com/" then return false end elseif type == webview.CALLBACK_RESULT_EVAL_OK then print("Eval ok. Result: " .. data['result']) elseif type == webview.CALLBACK_RESULT_EVAL_ERROR then print("Eval not ok. Request # " .. request_id) end end local webview_id = webview.create(webview_callback) ``` ### webview.destroy *Type:* FUNCTION Destroys an instance of a webview. **Parameters** - `webview_id` (number) - The webview id (returned by the `webview.create()` call) ### webview.open *Type:* FUNCTION Opens a web page in the webview, using an URL. Once the request is done, the callback (registered in `webview.create()`) is invoked. **Parameters** - `webview_id` (number) - The webview id - `url` (string) - The URL to open - `options` (table) - A table of options for the request. Currently it holds these options: - `hidden` (boolean) - If true, the webview will stay hidden (default=false) - `headers` (table) - A table of header keys and values - `transparent` (boolean) - If true, the webview background will be transparent (default=false) **Examples** ``` local request_id = webview.open(webview_id, "http://www.defold.com", {hidden = true}) ``` ### webview.open_raw *Type:* FUNCTION Opens a web page in the webview, using HTML data. Once the request is done, the callback (registered in `webview.create()`) is invoked. **Parameters** - `webview_id` (number) - The webview id - `html` (string) - The HTML data to display - `options` (table) - A table of options for the request. See `webview.open()` **Examples** ``` local html = sys.load_resource("/main/data/test.html") local request_id = webview.open_raw(webview_id, html, {hidden = true}) ``` ### webview.eval *Type:* FUNCTION Evaluates JavaScript within the context of the currently loaded page (if any). Once the request is done, the callback (registered in `webview.create()`) is invoked. The callback will get the result in the `data["result"]` field. **Parameters** - `webview_id` (number) - The webview id - `code` (string) - The JavaScript code to evaluate **Examples** ``` local request_id = webview.eval(webview_id, "GetMyFormData()") ``` ### webview.set_transparent *Type:* FUNCTION Set transparency of webview background **Parameters** - `webview_id` (number) - The webview id - `transparent` (boolean) - If `true`, the webview background becomes transparent, otherwise opaque. ### webview.set_visible *Type:* FUNCTION Shows or hides a webview **Parameters** - `webview_id` (number) - The webview id - `visible` (number) - If `0`, hides the webview. If non zero, shows the view ### webview.is_visible *Type:* FUNCTION Returns the visibility state of the webview. **Parameters** - `webview_id` (number) - The webview id ### webview.set_position *Type:* FUNCTION Sets the position and size of the webview **Parameters** - `webview_id` (number) - The webview id - `x` (number) - The x position of the webview - `y` (number) - The y position of the webview - `width` (number) - The width of the webview (-1 to match screen width) - `height` (number) - The height of the webview (-1 to match screen height) ### CALLBACK_RESULT_URL_OK *Type:* VARIABLE ### CALLBACK_RESULT_URL_ERROR *Type:* VARIABLE ### CALLBACK_RESULT_URL_LOADING *Type:* VARIABLE ### CALLBACK_RESULT_EVAL_OK *Type:* VARIABLE ### CALLBACK_RESULT_EVAL_ERROR *Type:* VARIABLE # extension-xsolla {#apis:extension-xsolla_shop} **Namespace:** `shop` **Language:** Lua **Type:** Extension Functions to use the Xsolla Shop Builder API. ## API ### shop.cancel *Type:* FUNCTION Cancel a cancellation token **Parameters** - `token` (table) - The cancellation token ### shop.cancellation_token *Type:* FUNCTION Create a cancellation token **Returns** - `table` - A cancellation token ### shop.set_bearer_token *Type:* FUNCTION Set a bearer token **Parameters** - `token` (string) - The bearer token ### shop.set_username_password *Type:* FUNCTION Set a username and password for basic authentication **Parameters** - `username` (string) - The username - `password` (string) - The password ### shop.set_merchant_auth *Type:* FUNCTION Set merchant id and api key for use with 'basicMerchantAuth' authentication **Parameters** - `merchant_id` (string) - The merchant id - `api_key` (string) - The API key ### shop.set_auth_for_cart *Type:* FUNCTION Set authorization when using 'AuthForCart' authentication **Parameters** - `authorization_id` (string) - Unique authorization id - `user` (string) - The user email ### shop.sync *Type:* FUNCTION Run code within a coroutine. **Parameters** - `fn` (function) - The function to run - `cancellation_token` (table) - Optional cancellation token ### shop.get_payment_url *Type:* FUNCTION get the payment url for an order **Parameters** - `order` (table) - `is_sandbox` (boolean) **Returns** - `string` ### shop.get_bundle_list *Type:* FUNCTION Get list of bundles **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `limit` (integer) - Limit for the number of elements on the page. - `offset` (integer) - Number of the element from which the list is generated (the count starts from 0). - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `additional_fields` (array) - The list of additional fields. These fields will be in the response if you send them in your request. - `country` (string) - Two-letter uppercase country code per [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Check the documentation for detailed information about [countries supported by Xsolla](https://developers.xsolla.com/doc/shop-builder/references/supported-countries/) and [the process of determining the country](https://developers.xsolla.com/doc/shop-builder/features/pricing-policy/#pricing_policy_country_determination). - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_bundle *Type:* FUNCTION Get specified bundle **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `sku (REQUIRED)` (string) - Bundle SKU. - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_bundle_list_in_group *Type:* FUNCTION Get list of bundles by specified group **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `external_id (REQUIRED)` (string) - Group external ID. - `limit` (integer) - Limit for the number of elements on the page. - `offset` (integer) - Number of the element from which the list is generated (the count starts from 0). - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `additional_fields` (array) - The list of additional fields. These fields will be in the response if you send them in your request. - `country` (string) - Two-letter uppercase country code per [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Check the documentation for detailed information about [countries supported by Xsolla](https://developers.xsolla.com/doc/shop-builder/references/supported-countries/) and [the process of determining the country](https://developers.xsolla.com/doc/shop-builder/features/pricing-policy/#pricing_policy_country_determination). - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_cart_by_id *Type:* FUNCTION Get cart by cart ID **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `cart_id (REQUIRED)` (string) - Cart ID. - `currency` (string) - The item price currency displayed in the cart. Three-letter currency code per [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217). Check the documentation for detailed information about [currencies supported by Xsolla](https://developers.xsolla.com/doc/pay-station/references/supported-currencies/). - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_user_cart *Type:* FUNCTION Get current user's cart **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `currency` (string) - The item price currency displayed in the cart. Three-letter currency code per [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217). Check the documentation for detailed information about [currencies supported by Xsolla](https://developers.xsolla.com/doc/pay-station/references/supported-currencies/). - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.cart_clear_by_id *Type:* FUNCTION Delete all cart items by cart ID **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `cart_id (REQUIRED)` (string) - Cart ID. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.cart_clear *Type:* FUNCTION Delete all cart items from current cart **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.cart_fill *Type:* FUNCTION Fill cart with items **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `body` (table) - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token **Examples** ``` { items = { { sku = "com.xsolla.booster_mega_1", quantity = 123, }, }, } ``` ### shop.cart_fill_by_id *Type:* FUNCTION Fill specific cart with items **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `cart_id (REQUIRED)` (string) - Cart ID. - `body` (table) - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token **Examples** ``` { items = { { sku = "com.xsolla.booster_mega_1", quantity = 123, }, }, } ``` ### shop.put_item_by_cart_id *Type:* FUNCTION Update cart item by cart ID **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `cart_id (REQUIRED)` (string) - Cart ID. - `item_sku (REQUIRED)` (string) - Item SKU. - `body` (table) - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token **Examples** ``` { quantity = 123.456, } ``` ### shop.delete_item_by_cart_id *Type:* FUNCTION Delete cart item by cart ID **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `cart_id (REQUIRED)` (string) - Cart ID. - `item_sku (REQUIRED)` (string) - Item SKU. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.put_item *Type:* FUNCTION Update cart item from current cart **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `item_sku (REQUIRED)` (string) - Item SKU. - `body` (table) - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token **Examples** ``` { quantity = 123.456, } ``` ### shop.delete_item *Type:* FUNCTION Delete cart item from current cart **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `item_sku (REQUIRED)` (string) - Item SKU. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.create_order_by_cart_id *Type:* FUNCTION Create order with all items from particular cart **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `cart_id (REQUIRED)` (string) - Cart ID. - `body` (table) - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token **Examples** ``` { currency = "Order price currency. Three-letter currency code per [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217). Check the documentation for detailed information about [currencies supported by Xsolla](https://developers.xsolla.com/doc/pay-station/references/supported-currencies/).", locale = "Response language.", sandbox = true, settings = { cart_payment_settings_ui = { theme = "Payment UI theme. Can be `63295a9a2e47fab76f7708e1` for the light theme (default) or `63295aab2e47fab76f7708e3` for the dark theme. You can also [create a custom theme](https://developers.xsolla.com/doc/pay-station/features/ui-theme-customization/#pay_station_ui_theme_customization_in_token) and pass its ID in this parameter.", desktop = { header = { is_visible = true, visible_logo = true, visible_name = true, visible_purchase = true, type = "How to show the header. Can be `compact` (hides project name and user ID) or `normal` (default).", close_button = true, }, }, mode = "Interface mode in payment UI. Can be `user_account` only. The header contains only the account navigation menu, and the user cannot select a product or make a payment. This mode is only available on the desktop.", user_account = { payment_accounts = { enable = true, }, info = { enable = true, order = 123, }, subscriptions = { enable = true, order = 123, }, }, header = { visible_virtual_currency_balance = true, }, mobile = { header = { close_button = true, }, }, is_prevent_external_link_open = true, is_payment_methods_list_mode = true, is_independent_windows = true, currency_format = "Set to `code` to display a three-letter [ISO 4217](https://developers.xsolla.com/doc/pay-station/references/supported-currencies/) currency code in the payment UI. The currency symbol is displayed instead of the three-letter currency code by default.", is_show_close_widget_warning = true, layout = "Location of the main elements of the payment UI. You can open the payment UI inside your game and/or swap the columns with information about an order and payment methods. Refer to the [customization instructions](https://developers.xsolla.com/doc/pay-station/features/ui-theme-customization/#pay_station_ui_theme_customization_layout) for detailed information.", is_three_ds_independent_windows = true, is_cart_open_by_default = true, }, cart_payment_settings_payment_method = 123, cart_payment_settings_return_url = "Page to redirect the user to after payment. Parameters `user_id`, `foreigninvoice`, `invoice_id` and `status` will be automatically added to the link.", cart_payment_redirect_policy = { redirect_conditions = "none", delay = 0, status_for_manual_redirection = "none", redirect_button_caption = "Text button", }, }, custom_parameters = { }, } ``` ### shop.create_order *Type:* FUNCTION Create order with all items from current cart **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `body` (table) - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token **Examples** ``` { currency = "Order price currency. Three-letter currency code per [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217). Check the documentation for detailed information about [currencies supported by Xsolla](https://developers.xsolla.com/doc/pay-station/references/supported-currencies/).", locale = "Response language.", sandbox = true, settings = { cart_payment_settings_ui = { theme = "Payment UI theme. Can be `63295a9a2e47fab76f7708e1` for the light theme (default) or `63295aab2e47fab76f7708e3` for the dark theme. You can also [create a custom theme](https://developers.xsolla.com/doc/pay-station/features/ui-theme-customization/#pay_station_ui_theme_customization_in_token) and pass its ID in this parameter.", desktop = { header = { is_visible = true, visible_logo = true, visible_name = true, visible_purchase = true, type = "How to show the header. Can be `compact` (hides project name and user ID) or `normal` (default).", close_button = true, }, }, mode = "Interface mode in payment UI. Can be `user_account` only. The header contains only the account navigation menu, and the user cannot select a product or make a payment. This mode is only available on the desktop.", user_account = { payment_accounts = { enable = true, }, info = { enable = true, order = 123, }, subscriptions = { enable = true, order = 123, }, }, header = { visible_virtual_currency_balance = true, }, mobile = { header = { close_button = true, }, }, is_prevent_external_link_open = true, is_payment_methods_list_mode = true, is_independent_windows = true, currency_format = "Set to `code` to display a three-letter [ISO 4217](https://developers.xsolla.com/doc/pay-station/references/supported-currencies/) currency code in the payment UI. The currency symbol is displayed instead of the three-letter currency code by default.", is_show_close_widget_warning = true, layout = "Location of the main elements of the payment UI. You can open the payment UI inside your game and/or swap the columns with information about an order and payment methods. Refer to the [customization instructions](https://developers.xsolla.com/doc/pay-station/features/ui-theme-customization/#pay_station_ui_theme_customization_layout) for detailed information.", is_three_ds_independent_windows = true, is_cart_open_by_default = true, }, cart_payment_settings_payment_method = 123, cart_payment_settings_return_url = "Page to redirect the user to after payment. Parameters `user_id`, `foreigninvoice`, `invoice_id` and `status` will be automatically added to the link.", cart_payment_redirect_policy = { redirect_conditions = "none", delay = 0, status_for_manual_redirection = "none", redirect_button_caption = "Text button", }, }, custom_parameters = { }, } ``` ### shop.create_order_with_item *Type:* FUNCTION Create order with specified item **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `item_sku (REQUIRED)` (string) - Item SKU. - `body` (table) - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token **Examples** ``` { currency = "Order price currency. Three-letter currency code per [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217). Check the documentation for detailed information about [currencies supported by Xsolla](https://developers.xsolla.com/doc/pay-station/references/supported-currencies/).", locale = "Response language.", sandbox = true, quantity = 123, promo_code = "Redeems a code of a promo code promotion with payment.", settings = { cart_payment_settings_ui = { theme = "Payment UI theme. Can be `63295a9a2e47fab76f7708e1` for the light theme (default) or `63295aab2e47fab76f7708e3` for the dark theme. You can also [create a custom theme](https://developers.xsolla.com/doc/pay-station/features/ui-theme-customization/#pay_station_ui_theme_customization_in_token) and pass its ID in this parameter.", desktop = { header = { is_visible = true, visible_logo = true, visible_name = true, visible_purchase = true, type = "How to show the header. Can be `compact` (hides project name and user ID) or `normal` (default).", close_button = true, }, }, mode = "Interface mode in payment UI. Can be `user_account` only. The header contains only the account navigation menu, and the user cannot select a product or make a payment. This mode is only available on the desktop.", user_account = { payment_accounts = { enable = true, }, info = { enable = true, order = 123, }, subscriptions = { enable = true, order = 123, }, }, header = { visible_virtual_currency_balance = true, }, mobile = { header = { close_button = true, }, }, is_prevent_external_link_open = true, is_payment_methods_list_mode = true, is_independent_windows = true, currency_format = "Set to `code` to display a three-letter [ISO 4217](https://developers.xsolla.com/doc/pay-station/references/supported-currencies/) currency code in the payment UI. The currency symbol is displayed instead of the three-letter currency code by default.", is_show_close_widget_warning = true, layout = "Location of the main elements of the payment UI. You can open the payment UI inside your game and/or swap the columns with information about an order and payment methods. Refer to the [customization instructions](https://developers.xsolla.com/doc/pay-station/features/ui-theme-customization/#pay_station_ui_theme_customization_layout) for detailed information.", is_three_ds_independent_windows = true, is_cart_open_by_default = true, }, cart_payment_settings_payment_method = 123, cart_payment_settings_return_url = "Page to redirect the user to after payment. Parameters `user_id`, `foreigninvoice`, `invoice_id` and `status` will be automatically added to the link.", cart_payment_redirect_policy = { redirect_conditions = "none", delay = 0, status_for_manual_redirection = "none", redirect_button_caption = "Text button", }, }, custom_parameters = { }, } ``` ### shop.create_free_order *Type:* FUNCTION Create order with free cart **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `body` (table) - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token **Examples** ``` { currency = "Order price currency. Three-letter currency code per [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217). Check the documentation for detailed information about [currencies supported by Xsolla](https://developers.xsolla.com/doc/pay-station/references/supported-currencies/).", locale = "Response language.", sandbox = true, settings = { cart_payment_settings_ui = { theme = "Payment UI theme. Can be `63295a9a2e47fab76f7708e1` for the light theme (default) or `63295aab2e47fab76f7708e3` for the dark theme. You can also [create a custom theme](https://developers.xsolla.com/doc/pay-station/features/ui-theme-customization/#pay_station_ui_theme_customization_in_token) and pass its ID in this parameter.", desktop = { header = { is_visible = true, visible_logo = true, visible_name = true, visible_purchase = true, type = "How to show the header. Can be `compact` (hides project name and user ID) or `normal` (default).", close_button = true, }, }, mode = "Interface mode in payment UI. Can be `user_account` only. The header contains only the account navigation menu, and the user cannot select a product or make a payment. This mode is only available on the desktop.", user_account = { payment_accounts = { enable = true, }, info = { enable = true, order = 123, }, subscriptions = { enable = true, order = 123, }, }, header = { visible_virtual_currency_balance = true, }, mobile = { header = { close_button = true, }, }, is_prevent_external_link_open = true, is_payment_methods_list_mode = true, is_independent_windows = true, currency_format = "Set to `code` to display a three-letter [ISO 4217](https://developers.xsolla.com/doc/pay-station/references/supported-currencies/) currency code in the payment UI. The currency symbol is displayed instead of the three-letter currency code by default.", is_show_close_widget_warning = true, layout = "Location of the main elements of the payment UI. You can open the payment UI inside your game and/or swap the columns with information about an order and payment methods. Refer to the [customization instructions](https://developers.xsolla.com/doc/pay-station/features/ui-theme-customization/#pay_station_ui_theme_customization_layout) for detailed information.", is_three_ds_independent_windows = true, is_cart_open_by_default = true, }, cart_payment_settings_payment_method = 123, cart_payment_settings_return_url = "Page to redirect the user to after payment. Parameters `user_id`, `foreigninvoice`, `invoice_id` and `status` will be automatically added to the link.", cart_payment_redirect_policy = { redirect_conditions = "none", delay = 0, status_for_manual_redirection = "none", redirect_button_caption = "Text button", }, }, custom_parameters = { }, } ``` ### shop.create_free_order_by_cart_id *Type:* FUNCTION Create order with particular free cart **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `cart_id (REQUIRED)` (string) - Cart ID. - `body` (table) - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token **Examples** ``` { currency = "Order price currency. Three-letter currency code per [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217). Check the documentation for detailed information about [currencies supported by Xsolla](https://developers.xsolla.com/doc/pay-station/references/supported-currencies/).", locale = "Response language.", sandbox = true, settings = { cart_payment_settings_ui = { theme = "Payment UI theme. Can be `63295a9a2e47fab76f7708e1` for the light theme (default) or `63295aab2e47fab76f7708e3` for the dark theme. You can also [create a custom theme](https://developers.xsolla.com/doc/pay-station/features/ui-theme-customization/#pay_station_ui_theme_customization_in_token) and pass its ID in this parameter.", desktop = { header = { is_visible = true, visible_logo = true, visible_name = true, visible_purchase = true, type = "How to show the header. Can be `compact` (hides project name and user ID) or `normal` (default).", close_button = true, }, }, mode = "Interface mode in payment UI. Can be `user_account` only. The header contains only the account navigation menu, and the user cannot select a product or make a payment. This mode is only available on the desktop.", user_account = { payment_accounts = { enable = true, }, info = { enable = true, order = 123, }, subscriptions = { enable = true, order = 123, }, }, header = { visible_virtual_currency_balance = true, }, mobile = { header = { close_button = true, }, }, is_prevent_external_link_open = true, is_payment_methods_list_mode = true, is_independent_windows = true, currency_format = "Set to `code` to display a three-letter [ISO 4217](https://developers.xsolla.com/doc/pay-station/references/supported-currencies/) currency code in the payment UI. The currency symbol is displayed instead of the three-letter currency code by default.", is_show_close_widget_warning = true, layout = "Location of the main elements of the payment UI. You can open the payment UI inside your game and/or swap the columns with information about an order and payment methods. Refer to the [customization instructions](https://developers.xsolla.com/doc/pay-station/features/ui-theme-customization/#pay_station_ui_theme_customization_layout) for detailed information.", is_three_ds_independent_windows = true, is_cart_open_by_default = true, }, cart_payment_settings_payment_method = 123, cart_payment_settings_return_url = "Page to redirect the user to after payment. Parameters `user_id`, `foreigninvoice`, `invoice_id` and `status` will be automatically added to the link.", cart_payment_redirect_policy = { redirect_conditions = "none", delay = 0, status_for_manual_redirection = "none", redirect_button_caption = "Text button", }, }, custom_parameters = { }, } ``` ### shop.create_free_order_with_item *Type:* FUNCTION Create order with specified free item **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `item_sku (REQUIRED)` (string) - Item SKU. - `body` (table) - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token **Examples** ``` { currency = "Order price currency. Three-letter currency code per [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217). Check the documentation for detailed information about [currencies supported by Xsolla](https://developers.xsolla.com/doc/pay-station/references/supported-currencies/).", locale = "Response language.", sandbox = true, quantity = 123, promo_code = "Redeems a code of a promo code promotion with payment.", settings = { cart_payment_settings_ui = { theme = "Payment UI theme. Can be `63295a9a2e47fab76f7708e1` for the light theme (default) or `63295aab2e47fab76f7708e3` for the dark theme. You can also [create a custom theme](https://developers.xsolla.com/doc/pay-station/features/ui-theme-customization/#pay_station_ui_theme_customization_in_token) and pass its ID in this parameter.", desktop = { header = { is_visible = true, visible_logo = true, visible_name = true, visible_purchase = true, type = "How to show the header. Can be `compact` (hides project name and user ID) or `normal` (default).", close_button = true, }, }, mode = "Interface mode in payment UI. Can be `user_account` only. The header contains only the account navigation menu, and the user cannot select a product or make a payment. This mode is only available on the desktop.", user_account = { payment_accounts = { enable = true, }, info = { enable = true, order = 123, }, subscriptions = { enable = true, order = 123, }, }, header = { visible_virtual_currency_balance = true, }, mobile = { header = { close_button = true, }, }, is_prevent_external_link_open = true, is_payment_methods_list_mode = true, is_independent_windows = true, currency_format = "Set to `code` to display a three-letter [ISO 4217](https://developers.xsolla.com/doc/pay-station/references/supported-currencies/) currency code in the payment UI. The currency symbol is displayed instead of the three-letter currency code by default.", is_show_close_widget_warning = true, layout = "Location of the main elements of the payment UI. You can open the payment UI inside your game and/or swap the columns with information about an order and payment methods. Refer to the [customization instructions](https://developers.xsolla.com/doc/pay-station/features/ui-theme-customization/#pay_station_ui_theme_customization_layout) for detailed information.", is_three_ds_independent_windows = true, is_cart_open_by_default = true, }, cart_payment_settings_payment_method = 123, cart_payment_settings_return_url = "Page to redirect the user to after payment. Parameters `user_id`, `foreigninvoice`, `invoice_id` and `status` will be automatically added to the link.", cart_payment_redirect_policy = { redirect_conditions = "none", delay = 0, status_for_manual_redirection = "none", redirect_button_caption = "Text button", }, }, custom_parameters = { }, } ``` ### shop.get_order *Type:* FUNCTION Get order **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `order_id (REQUIRED)` (string) - Order ID. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_upsell_for_project_client *Type:* FUNCTION Get list of upsell items in project **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_games_list *Type:* FUNCTION Get games list **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `limit` (integer) - Limit for the number of elements on the page. - `offset` (integer) - Number of the element from which the list is generated (the count starts from 0). - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `additional_fields` (array) - The list of additional fields. These fields will be in the response if you send them in your request. - `country` (string) - Two-letter uppercase country code per [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Check the documentation for detailed information about [countries supported by Xsolla](https://developers.xsolla.com/doc/shop-builder/references/supported-countries/) and [the process of determining the country](https://developers.xsolla.com/doc/shop-builder/features/pricing-policy/#pricing_policy_country_determination). - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_games_group *Type:* FUNCTION Get games list by specified group **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `external_id (REQUIRED)` (string) - Group external ID. - `limit` (integer) - Limit for the number of elements on the page. - `offset` (integer) - Number of the element from which the list is generated (the count starts from 0). - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `additional_fields` (array) - The list of additional fields. These fields will be in the response if you send them in your request. - `country` (string) - Two-letter uppercase country code per [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Check the documentation for detailed information about [countries supported by Xsolla](https://developers.xsolla.com/doc/shop-builder/references/supported-countries/) and [the process of determining the country](https://developers.xsolla.com/doc/shop-builder/features/pricing-policy/#pricing_policy_country_determination). - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_game_by_sku *Type:* FUNCTION Get game for catalog **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `item_sku (REQUIRED)` (string) - Item SKU. - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `additional_fields` (array) - The list of additional fields. These fields will be in the response if you send them in your request. - `country` (string) - Two-letter uppercase country code per [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Check the documentation for detailed information about [countries supported by Xsolla](https://developers.xsolla.com/doc/shop-builder/references/supported-countries/) and [the process of determining the country](https://developers.xsolla.com/doc/shop-builder/features/pricing-policy/#pricing_policy_country_determination). - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_game_key_by_sku *Type:* FUNCTION Get game key for catalog **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `item_sku (REQUIRED)` (string) - Item SKU. - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `additional_fields` (array) - The list of additional fields. These fields will be in the response if you send them in your request. - `country` (string) - Two-letter uppercase country code per [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Check the documentation for detailed information about [countries supported by Xsolla](https://developers.xsolla.com/doc/shop-builder/references/supported-countries/) and [the process of determining the country](https://developers.xsolla.com/doc/shop-builder/features/pricing-policy/#pricing_policy_country_determination). - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_game_keys_group *Type:* FUNCTION Get game keys list by specified group **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `external_id (REQUIRED)` (string) - Group external ID. - `limit` (integer) - Limit for the number of elements on the page. - `offset` (integer) - Number of the element from which the list is generated (the count starts from 0). - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `additional_fields` (array) - The list of additional fields. These fields will be in the response if you send them in your request. - `country` (string) - Two-letter uppercase country code per [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Check the documentation for detailed information about [countries supported by Xsolla](https://developers.xsolla.com/doc/shop-builder/references/supported-countries/) and [the process of determining the country](https://developers.xsolla.com/doc/shop-builder/features/pricing-policy/#pricing_policy_country_determination). - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_drm_list *Type:* FUNCTION Get DRM list **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_user_games *Type:* FUNCTION Get list of games owned by user **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `limit` (integer) - Limit for the number of elements on the page. - `offset` (integer) - Number of the element from which the list is generated (the count starts from 0). - `sandbox` (integer) - What type of entitlements should be returned. If the parameter is set to 1, the entitlements received by the user in the sandbox mode only are returned. If the parameter isn't passed or is set to 0, the entitlements received by the user in the live mode only are returned. - `additional_fields` (array) - The list of additional fields. These fields will be in the response if you send them in your request. Available fields `attributes`. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.redeem_game_pin_code *Type:* FUNCTION Redeem game code by client **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `body` (table) - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token **Examples** ``` { code = "AAAA-BBBB-CCCC-DDDD", sandbox = false, } ``` ### shop.redeem_coupon *Type:* FUNCTION Redeem coupon code **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `body` (table) - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token **Examples** ``` { coupon_code = "WINTER2021", selected_unit_items = { }, } ``` ### shop.get_coupon_rewards_by_code *Type:* FUNCTION Get coupon rewards **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `coupon_code (REQUIRED)` (string) - Unique case sensitive code. Contains letters and numbers. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.redeem_promo_code *Type:* FUNCTION Redeem promo code **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `body` (table) - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token **Examples** ``` { coupon_code = "SUMMER2021", cart = { id = "Cart ID.", }, selected_unit_items = { }, } ``` ### shop.remove_cart_promo_code *Type:* FUNCTION Remove promo code from cart **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `body` (table) - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token **Examples** ``` { cart = { id = "Cart ID.", }, } ``` ### shop.get_promo_code_rewards_by_code *Type:* FUNCTION Get promo code rewards **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `promocode_code (REQUIRED)` (string) - Unique case sensitive code. Contains letters and numbers. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.verify_promotion_code *Type:* FUNCTION Verify promotion code **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `code (REQUIRED)` (string) - Unique case-sensitive code. Contains letters and numbers. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_virtual_items *Type:* FUNCTION Get virtual items list **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `limit` (integer) - Limit for the number of elements on the page. - `offset` (integer) - Number of the element from which the list is generated (the count starts from 0). - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `additional_fields` (array) - The list of additional fields. These fields will be in the response if you send them in your request. - `country` (string) - Two-letter uppercase country code per [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Check the documentation for detailed information about [countries supported by Xsolla](https://developers.xsolla.com/doc/shop-builder/references/supported-countries/) and [the process of determining the country](https://developers.xsolla.com/doc/shop-builder/features/pricing-policy/#pricing_policy_country_determination). - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_virtual_items_sku *Type:* FUNCTION Get virtual item by SKU **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `item_sku (REQUIRED)` (string) - Item SKU. - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `country` (string) - Two-letter uppercase country code per [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Check the documentation for detailed information about [countries supported by Xsolla](https://developers.xsolla.com/doc/shop-builder/references/supported-countries/) and [the process of determining the country](https://developers.xsolla.com/doc/shop-builder/features/pricing-policy/#pricing_policy_country_determination). - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_all_virtual_items *Type:* FUNCTION Get all virtual items list **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_virtual_currency *Type:* FUNCTION Get virtual currency list **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `limit` (integer) - Limit for the number of elements on the page. - `offset` (integer) - Number of the element from which the list is generated (the count starts from 0). - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `additional_fields` (array) - The list of additional fields. These fields will be in the response if you send them in your request. - `country` (string) - Two-letter uppercase country code per [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Check the documentation for detailed information about [countries supported by Xsolla](https://developers.xsolla.com/doc/shop-builder/references/supported-countries/) and [the process of determining the country](https://developers.xsolla.com/doc/shop-builder/features/pricing-policy/#pricing_policy_country_determination). - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_virtual_currency_sku *Type:* FUNCTION Get virtual currency by SKU **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `virtual_currency_sku (REQUIRED)` (string) - Virtual currency SKU. - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `country` (string) - Two-letter uppercase country code per [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Check the documentation for detailed information about [countries supported by Xsolla](https://developers.xsolla.com/doc/shop-builder/references/supported-countries/) and [the process of determining the country](https://developers.xsolla.com/doc/shop-builder/features/pricing-policy/#pricing_policy_country_determination). - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_virtual_currency_package *Type:* FUNCTION Get virtual currency package list **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `limit` (integer) - Limit for the number of elements on the page. - `offset` (integer) - Number of the element from which the list is generated (the count starts from 0). - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `additional_fields` (array) - The list of additional fields. These fields will be in the response if you send them in your request. - `country` (string) - Two-letter uppercase country code per [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Check the documentation for detailed information about [countries supported by Xsolla](https://developers.xsolla.com/doc/shop-builder/references/supported-countries/) and [the process of determining the country](https://developers.xsolla.com/doc/shop-builder/features/pricing-policy/#pricing_policy_country_determination). - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_virtual_currency_package_sku *Type:* FUNCTION Get virtual currency package by SKU **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `virtual_currency_package_sku (REQUIRED)` (string) - Virtual currency package SKU. - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `country` (string) - Two-letter uppercase country code per [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Check the documentation for detailed information about [countries supported by Xsolla](https://developers.xsolla.com/doc/shop-builder/references/supported-countries/) and [the process of determining the country](https://developers.xsolla.com/doc/shop-builder/features/pricing-policy/#pricing_policy_country_determination). - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_virtual_items_group *Type:* FUNCTION Get items list by specified group **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `external_id (REQUIRED)` (string) - Group external ID. - `limit` (integer) - Limit for the number of elements on the page. - `offset` (integer) - Number of the element from which the list is generated (the count starts from 0). - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `additional_fields` (array) - The list of additional fields. These fields will be in the response if you send them in your request. - `country` (string) - Two-letter uppercase country code per [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Check the documentation for detailed information about [countries supported by Xsolla](https://developers.xsolla.com/doc/shop-builder/references/supported-countries/) and [the process of determining the country](https://developers.xsolla.com/doc/shop-builder/features/pricing-policy/#pricing_policy_country_determination). - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_item_groups *Type:* FUNCTION Get item group list **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.create_order_with_item_for_virtual_currency *Type:* FUNCTION Create order with specified item purchased by virtual currency **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `item_sku (REQUIRED)` (string) - Item SKU. - `virtual_currency_sku (REQUIRED)` (string) - Virtual currency SKU. - `platform` (string) - Publishing platform the user plays on `xsolla` (default), `playstation_network`, `xbox_live`, `pc_standalone`, `nintendo_shop`, `google_play`, `app_store_ios`, `android_standalone`, `ios_standalone`, `android_other`, `ios_other`, `pc_other`. - `body` (table) - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token **Examples** ``` { custom_parameters = { }, } ``` ### shop.get_sellable_items *Type:* FUNCTION Get sellable items list **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `limit` (integer) - Limit for the number of elements on the page. - `offset` (integer) - Number of the element from which the list is generated (the count starts from 0). - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `additional_fields` (array) - The list of additional fields. These fields will be in the response if you send them in your request. - `country` (string) - Two-letter uppercase country code per [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Check the documentation for detailed information about [countries supported by Xsolla](https://developers.xsolla.com/doc/shop-builder/references/supported-countries/) and [the process of determining the country](https://developers.xsolla.com/doc/shop-builder/features/pricing-policy/#pricing_policy_country_determination). - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_sellable_item_by_id *Type:* FUNCTION Get sellable item by ID **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `item_id (REQUIRED)` (string) - Item ID. - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_sellable_item_by_sku *Type:* FUNCTION Get sellable item by SKU **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `sku (REQUIRED)` (string) - Item SKU. - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_sellable_items_group *Type:* FUNCTION Get sellable items list by specified group **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `external_id (REQUIRED)` (string) - Group external ID. - `limit` (integer) - Limit for the number of elements on the page. - `offset` (integer) - Number of the element from which the list is generated (the count starts from 0). - `locale` (string) - Response language. Two-letter lowercase language code per ISO 639-1. - `additional_fields` (array) - The list of additional fields. These fields will be in the response if you send them in your request. - `country` (string) - Two-letter uppercase country code per [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). Check the documentation for detailed information about [countries supported by Xsolla](https://developers.xsolla.com/doc/shop-builder/references/supported-countries/) and [the process of determining the country](https://developers.xsolla.com/doc/shop-builder/features/pricing-policy/#pricing_policy_country_determination). - `promo_code` (string) - Unique case sensitive code. Contains letters and numbers. - `show_inactive_time_limited_items` (integer) - Shows time-limited items that are not available to the user. The validity period of such items has not started or has already expired. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_reward_chains_list *Type:* FUNCTION Get current user's reward chains **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `limit` (integer) - Limit for the number of elements on the page. - `offset` (integer) - Number of the element from which the list is generated (the count starts from 0). - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_user_reward_chain_balance *Type:* FUNCTION Get current user's value point balance **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `reward_chain_id (REQUIRED)` (integer) - Reward chain ID. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.claim_user_reward_chain_step_reward *Type:* FUNCTION Claim step reward **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. You can find this parameter in your [Publisher Account](https://publisher.xsolla.com/) next to the name of the project. - `reward_chain_id (REQUIRED)` (integer) - Reward chain ID. - `step_id (REQUIRED)` (integer) - Reward chain step ID. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.get_user_clan_top_contributors *Type:* FUNCTION Get top 10 contributors to reward chain under clan **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. - `reward_chain_id (REQUIRED)` (integer) - Reward chain ID. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token ### shop.user_clan_update *Type:* FUNCTION Update current user's clan **Parameters** - `project_id (REQUIRED)` (integer) - Project ID. - `callback` (function) - Optional callback function - `retry_policy` (table) - Optional retry policy - `cancellation_token` (table) - Optional cancellation token # extension-zendesk {#apis:extension-zendesk_zendesk} **Namespace:** `zendesk` **Language:** Lua **Type:** Extension Defold native extension to interact with the Zendesk SDK. ## API ### zendesk.initialize *Type:* FUNCTION Initialize the Zendesk SDK ### zendesk.set_callback *Type:* FUNCTION Set a callback for events from the Zendesk SDK ### zendesk.show_messaging *Type:* FUNCTION Show the conversation screen. ### zendesk.set_conversation_fields *Type:* FUNCTION Set conversation fields in the SDK to add contextual data about the conversation. ### zendesk.clear_conversation_fields *Type:* FUNCTION Clear conversation fields from the SDK storage when the client side context changes. ### zendesk.set_conversation_tags *Type:* FUNCTION Set custom conversation tags in the SDK to add contextual data about the conversation. ### zendesk.clear_conversation_tags *Type:* FUNCTION Clear conversation tags from SDK storage when the client side context changes. ### zendesk.login *Type:* FUNCTION Authenticate a user. ### zendesk.logout *Type:* FUNCTION Unauthenticate a user. ### MSG_INIT_ERROR *Type:* VARIABLE An error was detected while initializing the Zendesk SDK ### MSG_INIT_SUCCESS *Type:* VARIABLE The Zendesk SDK has been initialized successfully ### MSG_INTERNAL_ERROR *Type:* VARIABLE An internal error occured ### MSG_ERROR *Type:* VARIABLE An generic error occured ### MSG_UNREAD_MESSAGE_COUNT_CHANGED *Type:* VARIABLE The number of unread messages has changed ### MSG_AUTHENTICATION_FAILED *Type:* VARIABLE A REST call failed for authentication reasons ### MSG_FIELD_VALIDATION_FAILED *Type:* VARIABLE Validation checks failed for conversation fields ### MSG_LOGIN_SUCCESS *Type:* VARIABLE Login was successful ### MSG_LOGIN_FAILED *Type:* VARIABLE Login failed ### MSG_LOGOUT_SUCCESS *Type:* VARIABLE Logout was successful ### MSG_LOGOUT_FAILED *Type:* VARIABLE Logout failed # Animation Delay - Wave {#examples:animation:animation_delay} This example shows how to use the delay parameter of `go.animate()` to create a wave effect. [Project files](https://github.com/defold/examples/tree/master/animation/animation_delay) This example shows how to use the `delay` parameter of `go.animate()` (or `gui.animate()`) to create a wave effect. ## Setup The collection contains four game objects aligned in a row next to each other. The additional `controller` game object has the script that starts one animation for each sprite. ## How It Works Four game objects start the same `position.y` ping-pong animation, but each one begins slightly later than the previous sprite. The result is a simple wave that makes the `delay` argument easy to see. The script stores the four target URLs in a table and loops over them with `ipairs()`. Each call to `go.animate()` uses the same target value, easing, duration, and playback mode. The only thing that changes per sprite is the argument: `delay`. Multiplying the sprite index by `0.15` seconds offsets each start time just enough to produce a clear staggered wave. ## Scripts ### animation_delay.script ```lua local TARGET_URLS = { "/ship_1", "/ship_2", "/ship_3", "/ship_4" } -- <1> local WAVE_HEIGHT = 420 -- <2> local STEP_DELAY = 0.15 function init(self) for i, url in ipairs(TARGET_URLS) do -- <3> go.animate(url, "position.y", go.PLAYBACK_LOOP_PINGPONG, WAVE_HEIGHT, go.EASING_INOUTSINE, 1.2, i * STEP_DELAY) -- <4> end end --[[ 1. The script animates the four game objects with sprites and in table we put the paths for the ships in the same collection. 2. All ships move to the same target peak Y value, and the wave is created by timing. 3. Loop over the four sprite game objects that should be animated. 4. Start the same ping-pong animation on each game object, but set the seventh `go.animate()` argument (`delay`) to `i * 0.15`. That staggered start time creates the wave effect. ]] ``` # Cancel animation {#examples:animation:cancel_animation} This example shows how to use `go.cancel_animations()` to stop a running animation and start a new one. [Project files](https://github.com/defold/examples/tree/master/animation/cancel_animation) The collection contains two game objects: - `ship` with one sprite and one script. - `description` with a label for displaying the instructions text ## How It Works The script starts an animation of movement along the X axis in `init()`. The ship starts moving to the right and back. Then it listens for input so it can interrupt that animation. Clicking or tapping cancels the currently played animations immediately and starts a new one to move the ship toward the new x position instead. When the player presses the mouse button or touches the screen, the script first calls [`go.cancel_animations()`](https://defold.com/ref/go-lua/index.html#go.cancel_animations:url-property). Defold stops the running tween and leaves the game object's position exactly where it was at that moment. The script then calls [`go.animate()`](https://defold.com/ref/go-lua/index.html#go.animate:url-property-playback-to-easing-duration-delay-complete_function) again with the clicked x coordinate as the new target. Because the old animation was canceled first, the new tween starts from the ship's current position instead of jumping back to the original starting point. ## Scripts ### cancel_animation.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> go.animate(".", "position.x", go.PLAYBACK_ONCE_FORWARD, 600, go.EASING_INOUTSINE, 5.0) -- <2> end function on_input(self, action_id, action) if (action_id == hash("mouse_button_left") or action_id == hash("touch")) and action.pressed then -- <3> go.cancel_animations(".", "position") -- <4> go.animate(".", "position.x", go.PLAYBACK_ONCE_FORWARD, action.x, go.EASING_INOUTSINE, 1.2) -- <5> end end --[[ 1. Acquire input focus so the script receives mouse clicks and touch presses. 2. Start with a long horizontal animation toward x = 600 so there is something to interrupt. 3. React to either a left mouse click or a touch press. 4. Cancel the running position animation. Defold keeps the property at its current value when the animation is canceled. 5. Start a new animation from that current x position toward the clicked x coordinate. ]] ``` # Cursor animation {#examples:animation:cursor} This example shows how to set and animate the normalized cursor value. [Project files](https://github.com/defold/examples/tree/master/animation/cursor) The example uses one game object with a sprite component and a label (to show the duration). The game object contains the script that sets and animates the normalized cursor value making the sprite's animation progress and shows the duration value on the label: ## Scripts ### cursor.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> -- Get the current value on component "sprite" self.duration = 0 -- <2> end function on_input(self, action_id, action) if action_id == hash("mouse_button_left") and action.pressed then -- <3> self.duration = self.duration + 1 -- <4> if self.duration > 3 then -- <5> self.duration = 0 end label.set_text("#info", "Cursor animation duration: "..self.duration) -- <6> go.cancel_animations("#sprite", "cursor") -- <7> go.set("#sprite", "cursor", 0.0) -- <8> go.animate("#sprite", "cursor", go.PLAYBACK_LOOP_FORWARD, 1, go.EASING_LINEAR, self.duration) -- <9> end end --[[ 1. Tell the engine that this object ("." is shorthand for the current game object) should listen to input. Any input will be received in the `on_input()` function. 2. Store a duration time used in this example (for defining how long the cursor animation should take) in self reference. 3. If we receive input (touch or mouse click) we change the duration of the cursor animation. 4. Increase the duration. 5. If the duration is larger than 3, set it back to 0 to make a circular change of the duration. 6. Set the text of the label with id `info` to show the current duration of the animation to user. 7. Cancel previous animation on cursor value. 8. Reset cursor value to 0. 9. Start new animation of cursor value with playback set to be looped and in foward direction (increasing cursor value), linear easing and new duration. --]] ``` # Custom easing - square wave {#examples:animation:custom_easing} This example shows how to define a custom easing curve and use it when animating with `go.animate()` instead of a built-in easing constant. [Project files](https://github.com/defold/examples/tree/master/animation/custom_easing) This example uses the square-wave easing curve. The logo alternates between its starting height and the target height, and the animation system interpolates the positions between the low and high positions when animating. ## Setup The collection contains one game object with one sprite and one script. The script animates only the `position.y` property with the custom easing. ## How It Works The script stores the custom easing samples in a plain Lua table and turns that table into a `vmath.vector`. Defold accepts that vector anywhere `go.animate()` (or `gui.animate()` in case of GUI animations) expects an easing value. Because the vector is made of repeated blocks of `0` and `1`, the animation keeps snapping between the start value (start y position) and the target value (520 on Y axis, which is above the start value). That makes the easing behave like a square wave instead of a continuous curve. Note that the animation system still interpolates between the frames, so depending on time, the animation can be more trapezoidal or more square wave. ## Scripts ### custom_easing.script ```lua local VALUES = { -- <1> 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, } local SQUARE_EASING = vmath.vector(VALUES) -- <2> function init(self) go.animate(".", "position.y", go.PLAYBACK_LOOP_FORWARD, 520, SQUARE_EASING, 4.0) -- <3> end --[[ 1. This table defines a custom easing curve with normalized samples between 0 and 1. Repeating blocks of zeroes and ones create a square-wave pattern. 2. Convert the Lua table into a `vmath.vector`, which `go.animate()` accepts as a custom easing value. 3. Animate the current game object's `position.y` sub-property. The custom curve makes the sprite move between its starting y position and 520 instead with interpolated in-between positions. ]] ``` # Easing Functions (Tweens) {#examples:animation:easing} Demonstrates different easing functions available in Defold. [Project files](https://github.com/defold/examples/tree/master/animation/easing) This example compares the built-in easing constants that can be passed to `go.animate()`. Use the left and right arrow keys, or the on-screen buttons, to switch easing function and restart the same position, rotation, and scale animations. ## What You'll Learn - How to pass built-in `go.EASING_*` constants to `go.animate()` - How `go.PLAYBACK_LOOP_PINGPONG` moves a property back and forth - How one script can animate different transform properties through script property overrides - How a controller can restart several game objects by sending messages ## Setup The collection contains one controller, one HUD, and three animated logo game objects: `demo` : Contains `controller.script`. It owns the current easing index, listens for left and right arrow input, and sends restart messages to the animated game objects. `position_demo` : Contains a logo sprite and `animator.script`. Its script properties override the start and end positions. `rotation_demo` : Contains a logo sprite and `animator.script`. Its script properties override the end Euler rotation. `scale_demo` : Contains a logo sprite and `animator.script`. Its script properties override the end scale. `hud` : Contains the GUI that shows the easing name, the easing graph, and the previous/next buttons. ## How It Works `controller.script` loads the table of easing constants from `easing_functions.lua`. When the selected index changes, it sends the chosen easing value to each animated game object in a `"restart"` message. Each animated game object uses the same `animator.script`. The script exposes start and end values for position, Euler rotation, and scale. In the collection, each game object overrides only the values it needs, so the position demo moves, the rotation demo rotates, and the scale demo scales. When `animator.script` receives a new easing value, it resets its game object to the configured start transform and starts a ping-pong property animation toward the configured end transform. The target values and duration stay the same while the selected easing constant changes the interpolation curve. Read more about property animations in the [manual](https://defold.com/manuals/property-animation/). ## Scripts ### animator.script ```lua go.property("start_position", vmath.vector3()) -- <1> go.property("end_position", vmath.vector3()) go.property("start_rotation", vmath.vector3()) go.property("end_rotation", vmath.vector3()) go.property("start_scale", vmath.vector3(1, 1, 1)) go.property("end_scale", vmath.vector3(1, 1, 1)) go.property("duration", 2) local RESTART = hash("restart") local function should_animate_position(self) return self.start_position ~= self.end_position -- <2> end local function should_animate_rotation(self) return self.start_rotation ~= self.end_rotation end local function should_animate_scale(self) return self.start_scale ~= self.end_scale end local function reset_position_rotation_scale(self) if should_animate_position(self) then go.set_position(self.start_position) -- <3> end if should_animate_rotation(self) then go.set(".", "euler", self.start_rotation) end if should_animate_scale(self) then go.set_scale(self.start_scale) end end local function animate(self) reset_position_rotation_scale(self) if should_animate_position(self) then go.animate(".", "position", go.PLAYBACK_LOOP_PINGPONG, self.end_position, self.easing, self.duration) -- <4> end if should_animate_rotation(self) then go.animate(".", "euler", go.PLAYBACK_LOOP_PINGPONG, self.end_rotation, self.easing, self.duration) end if should_animate_scale(self) then go.animate(".", "scale", go.PLAYBACK_LOOP_PINGPONG, self.end_scale, self.easing, self.duration) end end function on_message(self, message_id, message) if message_id == RESTART then self.easing = message.easing -- <5> animate(self) end end --[[ 1. These script properties can be overridden per game object in the collection. The example uses one script for all three demos and changes only the relevant start/end values. 2. A transform property is animated only when its start and end values differ. The position demo changes position, the rotation demo changes Euler rotation, and the scale demo changes scale. 3. Reset the game object before starting the animation so every easing function begins from the same visual state. 4. `go.animate()` uses ping-pong playback to animate from the start value to the end value and back again in a loop. 5. The controller sends the selected built-in `go.EASING_*` constant in a `restart` message. ]] ``` ### controller.script ```lua local EASING_FUNCTIONS = require("example.easing_functions") -- <1> local DEMO_URLS = { "position_demo", "rotation_demo", "scale_demo" } -- <2> local PREVIOUS = -1 local NEXT = 1 local PREV_EASING_DEMO = hash("prev_easing_demo") local NEXT_EASING_DEMO = hash("next_easing_demo") local DEMO_CHANGED = hash("demo_changed") local KEY_LEFT = hash("key_left") local KEY_RIGHT = hash("key_right") local RESTART = hash("restart") local function wrap_index(index) if index < 1 then return #EASING_FUNCTIONS elseif index > #EASING_FUNCTIONS then return 1 end return index end local function restart_demo_animations(easing) for _, url in ipairs(DEMO_URLS) do msg.post(url, RESTART, { easing = easing.value }) -- <3> end end local function update_gui(self) msg.post("/hud#gui", DEMO_CHANGED, { -- <4> index = self.index, total = #EASING_FUNCTIONS, easing_name = self.easing.name }) end local function change_easing_demo(self, index_change) self.index = wrap_index(self.index + index_change) -- <5> self.easing = EASING_FUNCTIONS.get_by_index(self.index) restart_demo_animations(self.easing) update_gui(self) end function init(self) msg.post(".", "acquire_input_focus") -- <6> self.index = 1 self.easing = EASING_FUNCTIONS.get_by_index(self.index) restart_demo_animations(self.easing) update_gui(self) end function final(self) msg.post(".", "release_input_focus") end function on_message(self, message_id) if message_id == PREV_EASING_DEMO then change_easing_demo(self, PREVIOUS) elseif message_id == NEXT_EASING_DEMO then change_easing_demo(self, NEXT) end end function on_input(self, action_id, action) if action_id == KEY_LEFT and action.pressed then -- <7> change_easing_demo(self, PREVIOUS) elseif action_id == KEY_RIGHT and action.pressed then change_easing_demo(self, NEXT) end end --[[ 1. The helper module stores the built-in easing constants together with display names for the HUD. 2. These child game objects all use `animator.script`, but their script property overrides make them animate different transform properties. 3. The controller does not animate the logos directly. It sends the selected easing constant to each animator in a `restart` message. 4. The HUD receives only presentation data: the current index, total count, and easing name. 5. Wrap the index so pressing left on the first easing function jumps to the last one, and pressing right on the last jumps back to the first. 6. The controller acquires input focus so it can receive keyboard actions from the built-in input binding. 7. The left and right arrow keys step through the easing list. ]] ``` # Euler Rotation {#examples:animation:euler_rotation} Shows how to animate Euler rotation. [Project files](https://github.com/defold/examples/tree/master/animation/euler_rotation) This example rotates a spinner sprite continuously by tweening one Euler angle. It uses the Z axis because that is the axis pointing out of the screen in a 2D scene. ## What You'll Learn - How to animate a game object's Euler rotation - Why `euler.z` is the useful axis for 2D rotation - How looping playback and linear easing create constant motion ## Setup The collection contains two game objects: `go` : Contains the sprite and `euler_rotation.script`. The sprite uses the `spinner` image from `sprites.atlas`, and the script animates only the game object's `euler.z` property. `description` : Contains the bottom description label. The label uses `/assets/text32.font`, a 32 px distance-field font, with `/builtins/fonts/label-df.material`. ## How It Works `go.animate()` can animate numeric game object properties and sub-properties. Here it targets `"."`, the current game object, and `"euler.z"`, the Z component of the Euler rotation vector. Euler angles are expressed in degrees, so the target value `-360` is one full clockwise turn. `go.PLAYBACK_LOOP_FORWARD` restarts the same two-second linear tween every time it finishes, keeping the spinner rotating at a constant speed. ## Scripts ### euler_rotation.script ```lua function init(self) go.animate(".", "euler.z", go.PLAYBACK_LOOP_FORWARD, -360, go.EASING_LINEAR, 2) -- <1> end --[[ 1. Animate the current game object's `euler.z` sub-property from its starting rotation to -360 degrees. The forward looping playback repeats the two-second linear tween, so the sprite keeps rotating clockwise. ]] ``` # Finite State Machines {#examples:animation:animation_states} Shows how to build a small Finite State Machine module and use it to control character and animation states. [Project files](https://github.com/defold/examples/tree/master/animation/animation_states) You can control the example in two ways: - Use the keyboard: `Left`/`Right` arrow keys, `Space`, `X`, and `C` - Click or touch the on-screen buttons: `idle`, `run`, `turn`, `jump`, `attack`, and `crouch` The keyboard `C` key is a held crouch input. The GUI `crouch` button toggles crouch on and off. This example shows how to build a small **Finite State Machine** (FSM) Lua module and use it in more than one place: - animation states in `knight.script` - locomotion states (`idle`, `run`) in `control.gui_script` - posture states (`standing`, `crouching`) in `control.gui_script` ## What You'll Learn - What Finite State Machines are - How to create generic FSM logic in a reusable Lua module - How to use multiple smaller FSMs for different control concerns - How to combine several control states into one animation target - How to insert intermediate animation states automatically ### Finite State Machines A **Finite-State Machine** is a model with a finite set of possible states, one active state at a time, and explicit rules for moving from one state to another. FSMs are used in digital logic, software, and AI because they make behavior depend on clear state and transition rules. Check also: - [Simplest Lua Finite State Machine on lua-users.org](http://lua-users.org/wiki/FiniteStateMachine) - [Lua Finite State Machine by Kyle Conroy](https://github.com/kyleconroy/lua-state-machine) - [Lua FSM by unindented](https://github.com/unindented/lua-fsm) - [Lua FSM by recih](https://github.com/recih/lua-fsm) - ["Simple Lua FSM" video by Mahri2D](https://www.youtube.com/watch?v=aVFMDiaQ_Qc) - ["How I think of state machines, coded in Defold" video by kags](https://www.youtube.com/watch?v=Hb3GEcTgkrg) ## Setup The collection contains two game objects: `gui` : Contains `control.gui` and `control.gui_script`. This script owns input focus, handles keyboard and pointer input, and uses two FSMs: one for locomotion (`idle` / `run`) and one for posture (`standing` / `crouching`). `knight` : Contains the sprite and `knight.script`. This script owns the animation FSM. It stores the current animation state, validates transitions with the reusable FSM module, plays flipbooks, and notifies the GUI whenever the active animation changes. ## Input The GUI stores raw input intent, then the locomotion and posture FSMs turn that intent into stable control states: - locomotion FSM: `idle` or `run` - posture FSM: `standing` or `crouching` For keyboard movement, the most recently pressed direction key wins. That lets the turn animation finish and continue into a run as long as one movement key is still held. The example uses these input bindings: Key Triggers: - `Space` - jump - `C` - crouch - `X` - attack - `Right` - right - `Left` - left Mouse Triggers: - `Button left` -touch (for left mouse clicks and touch input) ## How It Works The example separates three different jobs: ### Reusable FSM module `fsm.lua` contains the generic part: - create a machine with `new()` - read state with `get_state_name()` and `get_state()` - perform direct transitions with `set_state()` - find multi-step routes with `find_path()` This keeps the reusable code small and focused. ### Animation FSM The knight owns one animation FSM with states such as: - `standing_idle` - `standing_run` - `standing_jump` - `standing_turn` - `crouching_idle` - `crouching_run` - `to_crouch` - `to_standing` When the requested animation is not directly reachable, the knight asks `fsm.find_path()` for a legal route and automatically inserts intermediate animation states. This keeps the controller states simple while still allowing animated transitions such as standing up or crouching down. For example: - `standing_idle` → `crouching_run` becomes `standing_idle` → `to_crouch` → `crouching_run` - `crouching_run` → `standing_idle` becomes `crouching_run` → `to_standing` → `standing_idle` ### Control FSMs The GUI owns two simpler FSMs: - locomotion FSM: `idle` / `run` - posture FSM: `standing` / `crouching` These smaller machines are easier to understand than one larger controller state containing every combination directly. The GUI combines them into one animation target for the knight: - `standing` + `idle` -> `standing_idle` - `standing` + `run` -> `standing_run` - `crouching` + `idle` -> `crouching_idle` - `crouching` + `run` -> `crouching_run` The GUI sends stable looping targets with `set_target_state`. One-shot actions such as jump, attack, and turn are sent separately with `trigger_state`. ## Why Split It Like This? Using several small FSMs keeps each machine focused on one question: - locomotion asks: "idle or run?" - posture asks: "standing or crouching?" - animation asks: "which exact animation state should play now?" That is often easier to read and maintain than one large state table that tries to represent every control and animation concern at once. ## Animation Atlas The sprite component uses a flipbook atlas with the standing, crouching, attack, jump, and transition animations for the knight character. > This example uses the Free Knight Character by Nauris "aamatniekss": > https://aamatniekss.itch.io/fantasy-knight-free-pixelart-animated-character ## Scripts ### knight.script ```lua local fsm = require("example.fsm") local SET_TARGET_STATE = hash("set_target_state") local TRIGGER_STATE = hash("trigger_state") local ANIMATION_DONE = hash("animation_done") local ANIMATION_STATE_CHANGED = hash("animation_state_changed") local GUI_URL = "/gui#control" -- <1> local ANIMATION_STATES = { standing_idle = { animation = hash("idle"), loop = true }, standing_run = { animation = hash("run"), loop = true }, standing_jump = { animation = hash("jump"), loop = false }, standing_attack = { animation = hash("attack"), loop = false }, standing_turn = { animation = hash("turn_around"), loop = false }, crouching_idle = { animation = hash("crouch_idle"), loop = true }, crouching_run = { animation = hash("crouch_walk"), loop = true }, crouching_attack = { animation = hash("crouch_attack"), loop = false }, to_crouch = { animation = hash("to_crouch"), loop = false }, to_standing = { animation = hash("from_crouch"), loop = false } } -- <2> local ANIMATION_TRANSITIONS = { standing_idle = { "standing_run", "standing_jump", "standing_attack", "standing_turn", "to_crouch" }, standing_run = { "standing_idle", "standing_jump", "standing_attack", "standing_turn", "to_crouch" }, standing_jump = { "standing_idle", "standing_run", "standing_attack", "standing_turn", "to_crouch" }, standing_attack = { "standing_idle", "standing_run", "standing_jump", "standing_turn", "to_crouch" }, standing_turn = { "standing_idle", "standing_run", "standing_jump", "standing_attack", "to_crouch" }, crouching_idle = { "crouching_run", "crouching_attack", "to_standing" }, crouching_run = { "crouching_idle", "crouching_attack", "to_standing" }, crouching_attack = { "crouching_idle", "crouching_run", "to_standing" }, to_crouch = { "crouching_idle", "crouching_run", "crouching_attack" }, to_standing = { "standing_idle", "standing_run", "standing_jump", "standing_attack", "standing_turn" } } -- <3> local function get_animation_state_name(self) return fsm.get_state_name(self.animation_fsm) end -- <4> local function get_animation_state(self) return fsm.get_state(self.animation_fsm) end -- <5> local function stop_jump_effect(self) local position = go.get_position() go.cancel_animations(".", "position.y") go.set_position(vmath.vector3(position.x, self.ground_y, position.z)) end -- <6> local function start_jump_effect(self) stop_jump_effect(self) go.animate(".", "position.y", go.PLAYBACK_ONCE_PINGPONG, self.ground_y + 50, go.EASING_INOUTCUBIC, 0.6) end -- <7> local function apply_facing(self) self.facing_left = self.desired_facing_left sprite.set_hflip("#sprite", self.facing_left) end -- <8> local function refresh_visuals(self, previous_state_name) local state = get_animation_state(self) local current_state_name = get_animation_state_name(self) -- <9> if not state or not current_state_name then return end -- <10> if previous_state_name == "standing_jump" and current_state_name ~= "standing_jump" then stop_jump_effect(self) end -- <11> if current_state_name ~= "standing_turn" then apply_facing(self) end -- <12> sprite.play_flipbook("#sprite", state.animation) -- <13> if current_state_name == "standing_jump" then start_jump_effect(self) end -- <14> msg.post(GUI_URL, ANIMATION_STATE_CHANGED, { state = current_state_name }) end -- <15> local function enter_animation_state(self, next_state_name) local previous_state_name = get_animation_state_name(self) -- <16> if previous_state_name == next_state_name then if next_state_name ~= "standing_turn" then apply_facing(self) end return end -- <17> if not fsm.set_state(self.animation_fsm, next_state_name) then return end refresh_visuals(self, previous_state_name) end -- <18> local function advance_animation_fsm(self, allow_from_finished_state) local requested_state = self.trigger_state or self.target_state local current_state = get_animation_state(self) -- <19> if not requested_state then return end -- <20> if not allow_from_finished_state and current_state and not current_state.loop then return end -- <21> if requested_state == get_animation_state_name(self) then enter_animation_state(self, requested_state) return end local path = fsm.find_path(self.animation_fsm, requested_state) -- <22> if not path then return end -- <23> for _, next_state_name in ipairs(path) do enter_animation_state(self, next_state_name) if not get_animation_state(self).loop then return end end end function init(self) -- <24> self.animation_fsm = fsm.new({ states = ANIMATION_STATES, transitions = ANIMATION_TRANSITIONS }) self.target_state = "standing_idle" self.trigger_state = nil self.facing_left = false self.desired_facing_left = false self.ground_y = go.get_position().y -- <25> enter_animation_state(self, self.target_state) end function on_message(self, message_id, message) -- <26> if message_id == SET_TARGET_STATE then self.target_state = message.state self.desired_facing_left = message.facing_left advance_animation_fsm(self) -- <27> elseif message_id == TRIGGER_STATE then self.trigger_state = message.state self.desired_facing_left = message.facing_left advance_animation_fsm(self) -- <28> elseif message_id == ANIMATION_DONE then if get_animation_state_name(self) == "standing_turn" then apply_facing(self) end -- <29> if self.trigger_state == get_animation_state_name(self) then self.trigger_state = nil end -- <30> advance_animation_fsm(self, true) end end --[[ 1. `ANIMATION_STATES` is the data table for the knight animation FSM. Each state only stores the animation id and whether the state loops. 2. `ANIMATION_TRANSITIONS` is the animation graph. The knight may only move along these legal transitions. 3. `get_animation_state_name()` reads the current animation state id from the reusable FSM module. 4. `get_animation_state()` reads the current animation state's data table from the reusable FSM module. 5. `stop_jump_effect()` clears the extra Y movement used to visualize a jump and snaps the knight back to the ground height. 6. `start_jump_effect()` starts the temporary Y animation for the jump. This can stay simple because jump is not cancelable in this example. 7. `apply_facing()` updates the sprite horizontal flip from the direction requested by the GUI controller. 8. `refresh_visuals()` handles the visual side effects of entering a state. It does not choose the next state; it only updates how the current state looks. 9. This guard leaves the helper idle if it is called before the FSM has an active state. 10. When the FSM leaves `standing_jump`, the jump offset is removed so the knight returns to ground level. 11. `standing_turn` is special because the knight should keep the old facing until the turn animation finishes. 12. Every animation state plays its own configured flipbook on the sprite. 13. Entering `standing_jump` also starts the extra Y movement so the jump is easier to see. 14. The knight reports the active animation state to the GUI so the control panel can highlight the correct buttons. 15. `enter_animation_state()` is the one place where the knight animation FSM actually changes state. 16. Re-entering the same state does not restart the flipbook; it only applies a facing change when the state allows immediate facing updates. 17. `fsm.set_state()` performs one legal direct transition. If the transition is invalid, the function stops there. 18. `advance_animation_fsm()` is the main stepper for the animation FSM. It moves the knight toward the latest requested state. 19. If nothing has been requested, there is nothing for the animation FSM to do. 20. If a non-looping state is still playing, the knight waits for `animation_done` before continuing. 21. If the requested state is already active, the knight only needs to apply same-state side effects such as facing. 22. If the reusable FSM module cannot find a legal path, the knight ignores that request. 23. The animation FSM walks along the path until it reaches a non-looping state that must finish before the next step can happen. 24. The knight creates one reusable FSM instance for its animation logic. 25. The knight starts by entering `standing_idle` through the same helper used for all later state changes. 26. `set_target_state` updates the stable looping state the knight should eventually settle into. 27. `trigger_state` starts a one-shot state such as jump, attack, or turn. 28. Because `sprite.play_flipbook()` is called without a completion callback, Defold sends `animation_done` when a non-looping flipbook finishes. 29. After a one-shot trigger finishes, the trigger request is cleared so the knight can continue toward the latest stable target. 30. Passing `true` here allows the FSM to continue from the finished non-looping state instead of stopping on it. --]] ``` ### control.gui_script ```lua local fsm = require("example.fsm") local SET_TARGET_STATE = hash("set_target_state") local TRIGGER_STATE = hash("trigger_state") local ANIMATION_STATE_CHANGED = hash("animation_state_changed") local KNIGHT_URL = "/knight#knight" -- <1> local INPUT = { TOUCH = hash("touch"), LEFT = hash("left"), RIGHT = hash("right"), JUMP = hash("jump"), ATTACK = hash("attack"), CROUCH = hash("crouch") } local DEFAULT_COLOR = vmath.vector4(0.3, 0.4, 0.8, 1.0) local ACTIVE_COLOR = vmath.vector4(0.4, 0.5, 0.9, 1.0) -- <2> local LOCOMOTION_STATES = { idle = {}, run = {} } -- <3> local LOCOMOTION_TRANSITIONS = { idle = { "run" }, run = { "idle" } } -- <4> local POSTURE_STATES = { standing = {}, crouching = {} } -- <5> local POSTURE_TRANSITIONS = { standing = { "crouching" }, crouching = { "standing" } } -- <6> local STATE_HIGHLIGHTS = { standing_idle = { "idle" }, standing_run = { "run" }, standing_jump = { "jump" }, standing_attack = { "attack" }, standing_turn = { "turn_around" }, crouching_idle = { "crouch" }, crouching_run = { "run", "crouch" }, crouching_attack = { "attack", "crouch" }, to_crouch = { "crouch" }, to_standing = { "crouch" } } -- <7> local function get_locomotion_state(self) return fsm.get_state_name(self.locomotion_fsm) end -- <8> local function get_posture_state(self) return fsm.get_state_name(self.posture_fsm) end -- <9> local function update_button_visual(node, is_active) gui.set_color(node, is_active and ACTIVE_COLOR or DEFAULT_COLOR) end -- <10> local function refresh_buttons(self, state_name) for _, node in pairs(self.buttons) do update_button_visual(node, false) end for _, node_id in ipairs(STATE_HIGHLIGHTS[state_name] or {}) do update_button_visual(self.buttons[node_id], true) end end -- <11> local function is_keyboard_running(self) return self.keyboard_direction_left ~= nil end -- <12> local function refresh_keyboard_direction(self) if self.left_down and not self.right_down then self.keyboard_direction_left = true elseif self.right_down and not self.left_down then self.keyboard_direction_left = false elseif not self.left_down and not self.right_down then self.keyboard_direction_left = nil end end -- <13> local function get_requested_direction(self) if self.keyboard_direction_left ~= nil then return self.keyboard_direction_left end return self.direction_left end -- <14> local function update_control_fsms(self) local next_locomotion_state = "idle" local next_posture_state = "standing" if self.run_requested or is_keyboard_running(self) then next_locomotion_state = "run" end if self.crouch_toggled or self.crouch_down then next_posture_state = "crouching" end if next_locomotion_state ~= get_locomotion_state(self) then fsm.set_state(self.locomotion_fsm, next_locomotion_state) end if next_posture_state ~= get_posture_state(self) then fsm.set_state(self.posture_fsm, next_posture_state) end end -- <15> local function get_base_state(self) local locomotion_state = get_locomotion_state(self) local posture_state = get_posture_state(self) if posture_state == "crouching" then return locomotion_state == "run" and "crouching_run" or "crouching_idle" end return locomotion_state == "run" and "standing_run" or "standing_idle" end -- <16> local function send_base_state(self) msg.post(KNIGHT_URL, SET_TARGET_STATE, { state = get_base_state(self), facing_left = self.direction_left }) end -- <17> local function send_trigger_state(self, state_name) msg.post(KNIGHT_URL, TRIGGER_STATE, { state = state_name, facing_left = self.direction_left }) end -- <18> local function sync_knight(self, play_turn_animation) local previous_direction_left = self.direction_left self.direction_left = get_requested_direction(self) update_control_fsms(self) -- <19> if play_turn_animation and previous_direction_left ~= self.direction_left and get_posture_state(self) == "standing" then send_trigger_state(self, "standing_turn") end send_base_state(self) end -- <20> local function request_idle(self) self.run_requested = false sync_knight(self) end -- <21> local function request_run(self) self.run_requested = true sync_knight(self) end -- <22> local function request_turn(self) self.direction_left = not get_requested_direction(self) if get_posture_state(self) == "standing" then send_trigger_state(self, "standing_turn") end send_base_state(self) end -- <23> local function request_jump(self) if get_posture_state(self) == "crouching" then return end send_trigger_state(self, "standing_jump") end -- <24> local function request_attack(self) local attack_state = get_posture_state(self) == "crouching" and "crouching_attack" or "standing_attack" send_trigger_state(self, attack_state) end -- <25> local function request_crouch_toggle(self) self.crouch_toggled = not self.crouch_toggled sync_knight(self) end -- <26> local function press_button(self, node_id) if node_id == "idle" then request_idle(self) elseif node_id == "run" then request_run(self) elseif node_id == "turn_around" then request_turn(self) elseif node_id == "jump" then request_jump(self) elseif node_id == "attack" then request_attack(self) elseif node_id == "crouch" then request_crouch_toggle(self) end end -- <27> local function pick_button(self, x, y) for node_id, node in pairs(self.buttons) do if gui.pick_node(node, x, y) then return node_id end end return nil end function init(self) -- <28> self.buttons = { idle = gui.get_node("idle"), run = gui.get_node("run"), turn_around = gui.get_node("turn_around"), jump = gui.get_node("jump"), attack = gui.get_node("attack"), crouch = gui.get_node("crouch") } -- <29> self.locomotion_fsm = fsm.new({ states = LOCOMOTION_STATES, transitions = LOCOMOTION_TRANSITIONS, initial_state = "idle" }) self.posture_fsm = fsm.new({ states = POSTURE_STATES, transitions = POSTURE_TRANSITIONS, initial_state = "standing" }) self.left_down = false self.right_down = false self.keyboard_direction_left = nil self.crouch_down = false self.crouch_toggled = false self.run_requested = false self.direction_left = false refresh_buttons(self, "standing_idle") -- <30> msg.post(".", "acquire_input_focus") send_base_state(self) end function on_input(self, action_id, action) -- <31> if action_id == INPUT.LEFT then if action.pressed then self.left_down = true self.keyboard_direction_left = true sync_knight(self, true) elseif action.released then self.left_down = false refresh_keyboard_direction(self) sync_knight(self) end -- <32> elseif action_id == INPUT.RIGHT then if action.pressed then self.right_down = true self.keyboard_direction_left = false sync_knight(self, true) elseif action.released then self.right_down = false refresh_keyboard_direction(self) sync_knight(self) end -- <33> elseif action_id == INPUT.CROUCH then if action.pressed then self.crouch_down = true sync_knight(self) elseif action.released then self.crouch_down = false sync_knight(self) end -- <34> elseif action_id == INPUT.JUMP and action.pressed then request_jump(self) -- <35> elseif action_id == INPUT.ATTACK and action.pressed then request_attack(self) -- <36> elseif action_id == INPUT.TOUCH and action.pressed then local node_id = pick_button(self, action.x, action.y) if node_id then press_button(self, node_id) return true end end end function on_message(self, message_id, message) -- <37> if message_id == ANIMATION_STATE_CHANGED then refresh_buttons(self, message.state) end end --[[ 1. `INPUT` stores the action hashes used by the GUI controller. 2. `LOCOMOTION_STATES` defines one small control FSM with the states `idle` and `run`. 3. `LOCOMOTION_TRANSITIONS` says that locomotion may move back and forth between `idle` and `run`. 4. `POSTURE_STATES` defines another control FSM with the states `standing` and `crouching`. 5. `POSTURE_TRANSITIONS` says that posture may move back and forth between `standing` and `crouching`. 6. `STATE_HIGHLIGHTS` maps animation states to the GUI buttons that should be highlighted. 7. `get_locomotion_state()` reads the current state of the locomotion FSM. 8. `get_posture_state()` reads the current state of the posture FSM. 9. `update_button_visual()` changes one button between its default and active color. 10. `refresh_buttons()` redraws the whole control panel from the animation state reported by the knight. 11. Keyboard running stays active while at least one direction key is held. 12. `refresh_keyboard_direction()` keeps the most recently active keyboard direction and clears it only when both direction keys are released. 13. `get_requested_direction()` uses the active keyboard direction when present, otherwise it keeps the direction remembered from GUI controls. 14. `update_control_fsms()` derives the locomotion and posture states from the stored run and crouch input flags. 15. `get_base_state()` combines the two control FSM states into one stable looping animation target for the knight. 16. `send_base_state()` tells the knight which looping animation state it should settle into next. 17. `send_trigger_state()` starts one-shot states such as jump, attack, or turn. 18. `sync_knight()` is the main controller helper. It updates direction, advances the two control FSMs, and then sends the correct animation requests. 19. A standing direction change can play the dedicated turn animation, but crouching just changes facing immediately because there is no crouch turn state. 20. Clicking the idle button clears the stored run request. 21. Clicking the run button sets the stored run request. 22. Clicking the turn button flips direction but keeps the current locomotion and posture states. 23. Jump is only requested while the posture FSM is in the `standing` state. 24. Attack chooses the standing or crouching attack from the current posture FSM state. 25. Toggling crouch changes the raw crouch intent, and then the two controller FSMs derive the correct stable states from it. 26. `press_button()` translates GUI node names into controller actions. 27. `pick_button()` checks which on-screen button was clicked. 28. `init()` caches the GUI nodes used by the control panel. 29. The GUI creates two reusable FSM instances: one for locomotion and one for posture. 30. The GUI script owns input focus, then sends the initial idle target to the knight. 31. Left key input updates both the raw held-key state and the active keyboard direction. 32. Right key input works the same way as left key input. 33. Keyboard crouch behaves like a held input, so pressing and releasing it directly updates the raw crouch flag. 34. Jump input sends a one-shot jump request. 35. Attack input sends a one-shot attack request. 36. The mouse or single-touch action uses `gui.pick_node()` so the on-screen buttons work as controls. 37. The GUI only changes its highlights when the knight reports a new active animation state. --]] ``` # Flipbook animation {#examples:animation:flipbook} This example shows how to use a flipbook animation in a sprite [Project files](https://github.com/defold/examples/tree/master/animation/flipbook) The sprite component in the game object uses a flipbook animation that is set up in an atlas: # Spine animation {#examples:animation:spine} This example shows Spine bone animation that blends when animation switches. [Project files](https://github.com/defold/examples/tree/master/animation/spine) ## Scripts ### spine.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> self.state = "idle" -- <2> end function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed then local properties = { blend_duration = 0.3 } -- <3> if self.state == "idle" then -- <4> spine.play_anim("#spinemodel", hash("run"), go.PLAYBACK_LOOP_FORWARD, properties) label.set_text("#label", "Click to idle...") self.state = "run" elseif self.state == "run" then -- <5> spine.play_anim("#spinemodel", hash("idle"), go.PLAYBACK_LOOP_FORWARD, properties) label.set_text("#label", "Click to run...") self.state = "idle" end end end --[[ 1. Tell the engine that this game object (".", which is shorthand for the current game object) should receive input. 2. Store state for this instance. Use a string that will be either "idle" or "run", reflecting the animation. 3. If user clicks, set up animation properties. Blend duration larger that 0 to get smoother transition between animations. 4. If state is currently "idle", play "run" animation, change text on label and change the state variable to "run". 5. If state is currently "run", play "idle" animation, change text on label and change the state variable to "idle". --]] ``` # Spinner animation {#examples:animation:spinner} This example shows how a game object is rotated in discrete steps, matching the graphics of the progress spinner. [Project files](https://github.com/defold/examples/tree/master/animation/spinner) ## Scripts ### spinner.script ```lua function init(self) self.t = 0 -- <1> self.speed = 16 -- <2> end function update(self, dt) self.t = self.t + dt -- <3> local step = math.floor(self.t * self.speed) -- <4> local angle = math.pi / 6 * step -- <5> local rot = vmath.quat_rotation_z(-angle) -- <6> go.set_rotation(rot) -- <7> end --[[ 1. Store a timer value (seconds elapsed) in the current script component (accessed through `self`). 2. A speed value. How many rotation steps to perform each second. 3. Increase timer value with the delta time elapsed since last `update()`. 4. Calculate which step to rotate to. 5. Calculate rotation angle (in radians) based on which step to rotate to. 6. Create a rotation quaternion with `angle` rotation around the Z axis. 7. Set the rotation on the current game object. --]] ``` # Tween animation {#examples:animation:basic_tween} This example shows how to tween animate the position of a game object. [Project files](https://github.com/defold/examples/tree/master/animation/basic_tween) ## Scripts ### spaceship.script ```lua function init(self) local to = vmath.vector3(400, 400, 0) -- <1> go.animate(".", "position", go.PLAYBACK_LOOP_PINGPONG, to, go.EASING_INOUTSINE, 2) -- <2> end --[[ 1. The destination to move the game object to (x, y, z) 2. This function animates the game object position to the destination and back again repeatedly over a period of 2 seconds. The movement uses a sine-wave easing curve to slow down at the end points. --]] ``` # Tween animations chain {#examples:animation:chained_tween} This example shows how to chain two tween animations of the position of a game object. In addition, the scale and tint is animated separately. [Project files](https://github.com/defold/examples/tree/master/animation/chained_tween) ## Scripts ### spaceship.script ```lua local up_down -- <1> local left_right function up_down(self) -- <2> go.animate(".", "position.y", go.PLAYBACK_ONCE_PINGPONG, 624, go.EASING_INOUTSINE, 2, 0, left_right) end function left_right(self) -- <3> go.animate(".", "position.x", go.PLAYBACK_ONCE_PINGPONG, 660, go.EASING_INOUTSINE, 2, 0, up_down) end function init(self) up_down(self) -- <4> go.animate(".", "scale.y", go.PLAYBACK_LOOP_PINGPONG, 0.5, go.EASING_INOUTSINE, 1) -- <5> go.animate("#sprite", "tint.x", go.PLAYBACK_LOOP_PINGPONG, 0.0, go.EASING_INOUTSINE, 1.5) -- <6> end --[[ 1. In Lua, local variables must be declared prior to their use. Since the functions `up_down()` and `left_right()` refer to each other we "forward declare" the names `up_down` and `left_right` before the function definitions. 2. This function animates the game object position's y component, then calls the function `left_right()` on completion. 3. This function animates the game object position's x component, then calls the function `up_down()` on completion. 4. Start by calling the `up_down()` function. 5. In parallel, tween the scale y component. 6. And the sprite's tint x component (which is the red value). --]] ``` # Message passing {#examples:basics:message_passing} This example shows how to communicate between two script components in two separate game objects. [Project files](https://github.com/defold/examples/tree/master/basics/message_passing) ## Scripts ### spaceship1.script ```lua local function landed(self) -- <2> label.set_text("#speech", "I'm there!") msg.post("spaceship2#script", "i'm there") end function on_message(self, message_id, message, sender) if message_id == hash("go to") then -- <1> label.set_text("#speech", "Ok...") go.animate(".", "position", go.PLAYBACK_ONCE_FORWARD, message.position, go.EASING_INOUTCUBIC, 1, 0, landed) end end --[[ 1. If someone sends us a "go to" message, set the speech label text and animate to the position supplied in the message data. At the end of animation, call the function `landed()` 2. This function is called when the position animation is completed. It sets the speech label text and then sends a message called "i'm there" to the component "script" in the "spaceship2" game object. --]] ``` ### spaceship2.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> self.moving = false -- <2> end local function landed(self) -- <6> self.moving = false label.set_text("#speech", "Hey, go to the opposite side!") local pos = go.get_position() local opposite = vmath.vector3() opposite.x = 720 - pos.x opposite.y = 720 - pos.y msg.post("spaceship1#script", "go to", { position = opposite }) end function on_message(self, message_id, message, sender) if message_id == hash("go to") then -- <5> self.moving = true label.set_text("#speech", "I'm going...") go.animate(".", "position", go.PLAYBACK_ONCE_FORWARD, message.position, go.EASING_INOUTCUBIC, 1.5, 0, landed) elseif message_id == hash("i'm there") then -- <7> label.set_text("#speech", "Great!") end end function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed and not self.moving then -- <3> local pos = vmath.vector3(action.x, action.y, 0) msg.post("#", "go to", { position = pos }) -- <4> end end --[[ 1. Tell the engine that we want to receive input. 2. Store a flag in the current script component instance that tells us if the spaceship is moving or not. 3. If user clicked and the spaceship is not moving. 4. Send a message to this script component ("#" is shorthand for that) saying "go to" and the clicked position as part of the message data. 5. If a "go to" message is received, set the speech label text and then animate the position of the current game object ("." is shorthand for that) to the position send in the message data. When the animation is done the function `landed()` is called. 6. When `landed()` is called on animation complete, set the label text, then calculate a position on the opposite of the screen and send a message called "go to" to the component "script" in the game object "spaceship11". Supplied with the message is the opposite position as message data. 7. If someone sends us a message called "i'm there" we react by just changing the speech label text. --]] ``` # Parent/child {#examples:basics:parent_child} This example shows how to child a game object to a parent. [Project files](https://github.com/defold/examples/tree/master/basics/parent_child) The parent/child relation is set up right in the editor by placing the parent and child game objects in the same collection and then simply dragging the child game object onto the parent. Note that such a hierarchy must be created in a collection if you do it in the editor. ## Scripts ### parent.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> local pos = go.get_position() -- <2> go.animate(".", "position.y", go.PLAYBACK_LOOP_PINGPONG, pos.y + 300, go.EASING_INOUTSINE, 3) -- <3> self.has_child = true -- <4> end function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed then if self.has_child then msg.post("child", "set_parent", { keep_world_transform = 1 }) -- <5> label.set_text("#label", "Click to child...") -- <6> else msg.post("child", "set_parent", { parent_id = go.get_id(), keep_world_transform = 1 }) -- <7> label.set_text("#label", "Click to detach...") -- <8> end self.has_child = not self.has_child -- <9> end end --[[ 1. Tell the engine that this game object wants to receive input. 2. Get the current position. 3. Animate the y position of this game object back and forth. 4. A flag to track if there is a child to this game object or not. Parent-child relations in Defold are only affecting the scene graph so we need to track this ourselves. 5. If the user clicks and there is a child, set the parent to nothing, meaning remove it as a child. 6. Set the label text accordingly. 7. If the user clicks and there is no child, set the parent to this game object. 8. Set the label text accordingly. 9. Set the flag to its inverse. --]] ``` ### child.script ```lua function init(self) go.animate(".", "euler.z", go.PLAYBACK_LOOP_FORWARD, 360, go.EASING_LINEAR, 1) -- <1> end --[[ 1. Animate the Z component of the euler rotation property on this game object. --]] ``` # Random numbers {#examples:basics:random_numbers} This example shows how to generate pseudo-random numbers in Defold using built-in math API. [Project files](https://github.com/defold/examples/tree/master/basics/random_numbers) In this example you'll learn how to generate pseudo-random numbers in Defold using built-in math API. In the example there is only a game object containing: - *Label* component where we show the text information - *Script* component where we generate random numbers Script sets the built-in random generator with a value of os.time() - which should be different every time you run it. Then produces 3 random numbers using math.random(). For more details refer to Defold API: [https://defold.com/ref/stable/math-lua/#math.random:m-n](https://defold.com/ref/stable/math-lua/#math.random:m-n) ## Scripts ### random_numbers.script ```lua function init(self) local seed = os.time() math.randomseed(seed) -- <1> label.set_text("#label", "Seed: " .. seed .. "\nRandom number (0 - 1): " .. math.random() -- <2> .. "\nRandom integer (1 - 100): " .. math.random(100) -- <3> .. "\nRandom integer (-10 - 0): " .. math.random(-10,0)) -- <4> end --[[ 1. First, set the randomseed. It can be specific, if you always want to generate same numbers, otherwise you can utilise e.g. os.time, like in the example to make it different each time. 2. math.random() with no arguments - generates a random floating point number between 0-1. 3. math.random(X) with one argument - generates an integer between 1 - X. 4. math.random(X, Y) with two arguments - generates an integer between X - Y. --]] ``` # Z-order {#examples:basics:z_order} This example shows how to put sprites in front and behind of eachother [Project files](https://github.com/defold/examples/tree/master/basics/z_order) There is one game object containing the logo sprite. It is set at Z position 0. The green spaceship is another game object containing a sprite. It is set at Z position 0.5. The pink spaceship is another game object containing a sprite. It is set at Z position -0.5. ## Scripts ### z_order.script ```lua function init(self) go.animate(".", "position.x", go.PLAYBACK_LOOP_PINGPONG, 600, go.EASING_INOUTSINE, 3) -- <1> end --[[ 1. Animate the game object's ("." is shorthand for the current game object) x position between start position and 600. --]] ``` # Proxy {#examples:collection:proxy} This example shows how to use collection proxies to load and unload collections. [Project files](https://github.com/defold/examples/tree/master/collection/proxy) The setup consists of several collections and game objects. proxy.collection : This is the bootstrap collection specified in `game.project`. Contains: - A *Script* that handles loading and unloading of collection proxies - Four *Collection proxies* referencing a menu collection and three level collections. menu.collection : This collection contains a menu. Contains: - A *GUI* with some box and text nodes that acts as buttons. - A *GUI script* that handles the logic of clicking on the buttons and sending messages back to the proxy.collection. level1-3.collection : Collections representing the levels of a game. Contains: - *Script* with logic to send a message back to the proxy.collection to show the menu again. ## Scripts ### controller.script ```lua local function show(self, proxy) -- <5> if self.current_proxy then -- <6> msg.post(self.current_proxy, "unload") -- <7> self.current_proxy = nil end msg.post(proxy, "async_load") -- <8> end function init(self) msg.post(".", "acquire_input_focus") -- <1> self.current_proxy = nil -- <2> msg.post("#", "show_menu") -- <3> end function on_message(self, message_id, message, sender) if message_id == hash("show_menu") then -- <4> show(self, "#menuproxy") elseif message_id == hash("show_level1") then show(self, "#level1proxy") elseif message_id == hash("show_level2") then show(self, "#level2proxy") elseif message_id == hash("show_level3") then show(self, "#level3proxy") elseif message_id == hash("proxy_loaded") then -- <9> self.current_proxy = sender -- <10> msg.post(sender, "enable") -- <11> elseif message_id == hash("proxy_unloaded") then print("Unloaded", sender) end end --[[ 1. Acquire input focus for this game object. This is required for input to be able to propagate into any of the collection proxies on the same game object as this script. 2. Create a variable `current_proxy` to track which collection proxy that is loaded. 3. Post a `show_menu` message to the `on_message` function of this script. This load and show the first screen. 4. Message handler that will react to `show_menu`, `show_level1`, `show_level2` and `show_level3` messages and load the appropriate collection proxy. 5. A helper function to unload any currently loaded collection proxy and load a new collection proxy. 6. Check if a collection proxy is loaded. 7. Send an `unload` message to the currently loaded collection proxy. This will immediately unload the proxy and all of its resources. A `proxy_unloaded` message will be sent when it has been unloaded. 8. Send an `async_load` message to the collection proxy that should be loaded. This will start loading the collection proxy and all of its resources. A `proxy_loaded` message will be sent when it has been loaded. 9. Handle the `proxy_loaded` message. This is sent when a collection proxy has finished loading. The collection and all resources will be loaded but no game objects or components will be active/enabled. 10. Store the url of the proxy that was loaded. This is used in the helper function to unload it when showing another collection proxy. 11. Enable the loaded collection proxy. This will activate/enable all game objects and components within the collection. --]] ``` ### menu.gui_script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> end function on_input(self, action_id, action) if action_id == hash("touch") and action.released then -- <2> if gui.pick_node(gui.get_node("level1"), action.x, action.y) then -- <3> msg.post("proxy:/controller#controller", "show_level1") -- <4> elseif gui.pick_node(gui.get_node("level2"), action.x, action.y) then msg.post("proxy:/controller#controller", "show_level2") elseif gui.pick_node(gui.get_node("level3"), action.x, action.y) then msg.post("proxy:/controller#controller", "show_level3") end end end --[[ 1. Acquire input focus for this script. 2. Check if a mouse click/screen touch is released. 3. Check if the mouse click/screen touch happened on top of any of the buttons. 4. Send a `show_level1` message to the controller script component in the `proxy` collection. --]] ``` ### level.script ```lua function init(self) msg.post(".", "acquire_input_focus") end function on_input(self, action_id, action) if action_id == hash("touch") and action.released then msg.post("proxy:/controller", "show_menu") end end ``` # Splash {#examples:collection:splash} This example shows how to use collection proxies to show a splash screen while loading a game menu. [Project files](https://github.com/defold/examples/tree/master/collection/splash) The setup consists of several collections and game objects. splash.collection : This is the bootstrap collection specified in `game.project`. Contains: - A *Script* that handles loading and unloading of collection proxies - Two *Collection proxies* referencing the splash screen and a menu collection. menu.collection : This collection contains a menu. Contains: - A *GUI* with some box and text nodes that acts as buttons. splashscreen.collection : Collections representing the splash screen. ## Scripts ### controller.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> msg.post("#splashscreenproxy", "async_load") -- <2> end function on_message(self, message_id, message, sender) if message_id == hash("proxy_loaded") then -- <3> if sender.fragment == hash("splashscreenproxy") then -- <4> msg.post("#splashscreenproxy", "enable") -- <5> msg.post("#menuproxy", "async_load") -- <6> self.menu_loading_started_time = os.time() -- <7> elseif sender.fragment == hash("menuproxy") then -- <8> local total_menu_loading_time = os.time() - self.menu_loading_started_time local minimum_splash_duration = 5 local delay = math.max(minimum_splash_duration - total_menu_loading_time, 0) -- <9> timer.delay(delay, false, function() -- <10> msg.post("#splashscreenproxy", "unload") -- <11> msg.post("#menuproxy", "enable") -- <12> end) end end end --[[ 1. Acquire input focus for this game object. This is required for input to be able to propagate into any of the collection proxies on the same game object as this script. 2. Load the splash screen 3. The "proxy_loaded" message is received whenever a collection proxy has been loaded 4. Here we check if it was the splash screen proxy which was loaded 5. Enable the splash screen proxy so that the splash screen is shown 6. Load the menu screen 7. Save the time when the menu screen loading was started 8. Was the menu proxy loaded? 9. Calculate how much longer the splash screen should remain visible, based on how long it took to load the menu 10. Start a timer for the remaining time 11. Unload the splash screen 12. Show the menu --]] ``` # Time-step {#examples:collection:timestep} This example shows how to speed up or slow down animations in a collection proxy by changing the time step of the collection proxy. [Project files](https://github.com/defold/examples/tree/master/collection/timestep) The setup consists of a `timestep.collection` and a `game.collection`. timestep.collection : This is the bootstrap collection specified in `game.project`. Contains: - A *Script* that handles loading of the `game.collection` and controls the time-step of `game.collection` using the `set_time_step` message. game.collection : This collection contains a "game" with some animated game objects. Contains: - Five animated game objects that are animated using `go.animate()` - A *Script* that starts the game object animations and lets the user control the time-step through messages sent to the *Script* in the `timestep.collection`. ## Scripts ### controller.script ```lua -- speed of the time in the collection proxy go.property("speed", 1) function init(self) -- acquire input for this script msg.post(".", "acquire_input_focus") -- load the collection proxy msg.post("#gameproxy", "async_load") end function update(self, dt) -- update the time step of the proxy each frame since it might be animated msg.post("#gameproxy", "set_time_step", { factor = self.speed, mode = 0 }) label.set_text("#label", tostring(self.speed)) end function on_message(self, message_id, message, sender) if message_id == hash("proxy_loaded") then msg.post(sender, "enable") elseif message_id == hash("animate_speed") then -- cancel any current animation of the speed property go.cancel_animations("#", "speed") -- start animation of the speed property local to = message.to local change = math.abs(self.speed - to) local rate_of_change = 2 local duration = change / rate_of_change go.animate("#", "speed", go.PLAYBACK_ONCE_FORWARD, to, go.EASING_LINEAR, duration) elseif message_id == hash("change_speed") then -- cancel any current animation of the speed property go.cancel_animations("#", "speed") -- make sure speed never goes below 0 self.speed = math.max(self.speed + message.amount, 0) end end ``` ### game.script ```lua function init(self) -- get input to this script msg.post(".", "acquire_input_focus") -- animate some game objects go.animate("enemy1", "position.x", go.PLAYBACK_LOOP_PINGPONG, 720, go.EASING_INOUTQUAD, 5, 0) go.animate("enemy2", "position.x", go.PLAYBACK_LOOP_PINGPONG, 720, go.EASING_INOUTQUAD, 5, 0.5) go.animate("enemy3", "position.x", go.PLAYBACK_LOOP_PINGPONG, 720, go.EASING_INOUTQUAD, 5, 1) go.animate("enemy4", "position.x", go.PLAYBACK_LOOP_PINGPONG, 720, go.EASING_INOUTQUAD, 5, 1.5) end function on_input(self, action_id, action) if action_id == hash("key_left") then msg.post("timestep:/controller", "change_speed", { amount = -0.01 }) elseif action_id == hash("key_right") then msg.post("timestep:/controller", "change_speed", { amount = 0.01 }) elseif action_id == hash("key_space") and action.pressed then -- flip self.to between 0 and 3 each time self.to = 3 - (self.to or 0) msg.post("timestep:/controller", "animate_speed", { to = self.to }) end end ``` # Physics debug {#examples:debug:physics} This example allows you to toggle physics debug visualization as well as changing the time step so the simulation runs at one tenth of the speed. [Project files](https://github.com/defold/examples/tree/master/debug/physics) With the physics visualization on, all collision object shapes are visible. In addition, at intersections the normals at the collision points are shown. The example collection consists of: - 4 blocks with dynamic collision objects with Restituion 1.0, so they bounce forever, - 4 walls with static collision objects forming boundaries for the blocks, - game object `go` with: - label with example description, - a script `physics.script` included below. This collection is additionally loaded via a `Collection Proxy` component in `main.collection`. Therefore, sending message `set_time_step` to its url `"main:/loader#physicsproxy"` is causing the proxy to have a different update time, causing e.g. the slow-motion effect, which might be helpful when debugging physics. ## Scripts ### physics.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> self.show_debug = false -- <2> end function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed then msg.post("@system:", "toggle_physics_debug") -- <3> if self.show_debug then -- <4> msg.post("main:/loader#physicsproxy", "set_time_step", { factor = 1, mode = 0 }) else msg.post("main:/loader#physicsproxy", "set_time_step", { factor = 0.1, mode = 1 }) end self.show_debug = not self.show_debug -- <5> end end --[[ 1. Make sure this game object's script component gets input from the engine. 2. A state flag to track if we show debug info or not. 3. If user clicks, toggle physics visualization. 4. In addition, we want to set the timestep. That is done through the collection proxy that loaded this example. Since we cannot get hold of the proxy from this side of it we message the loader game object in the main collection and it will relay the message to the proxy component. 5. Switch the `show_debug` flag. --]] ``` ### loader.script ```lua function init(self) msg.post(".", "acquire_input_focus") msg.post("#physicsproxy", "load") end function on_message(self, message_id, message, sender) if message_id == hash("proxy_loaded") then msg.post(sender, "init") msg.post(sender, "enable") end end ``` # Visual profiler {#examples:debug:profile} This example shows the on-screen profiler. It displays useful runtime information. [Project files](https://github.com/defold/examples/tree/master/debug/profile) For more in-depth analysis, the web profiler is usually more suitable. See [the debug manual](/manuals/debugging) for more information. ## Scripts ### profile.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> end function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed then msg.post("@system:", "toggle_profile") -- <2> end end --[[ 1. Make sure this game object's script component gets input from the engine. 2. If user clicks, toggle profiling information. --]] ``` # Dynamic factories {#examples:factory:dynamic} This example shows how to change the prototype game object used by a factory component. [Project files](https://github.com/defold/examples/tree/master/factory/dynamic) This example shows how to change the prototype game object used by a factory component. All prototype bullets are stored in a collection and referenced as a collection proxy. The collection proxy is never loaded, but it will ensure that the bullet prototypes are included in the build even though they are not immediately used by a factory. Another alternative is to load bullet prototypes using Live Update. ship : The red ship at the bottom. Contains: - A *Sprite* component with the spaceship image. - A *Factory* component to spawn bullet game objects. This component has the *Dynamic Protoype* option checked. - A *Collection Proxy* component referencing a collection containing all bullet types - A *Script* component to handle spawning of bullets. All bullets are added in the bullets.collection: The bullets.collection is referenced from the dynamic.collection as a collection proxy: ## Scripts ### dynamic.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- a list of different bullet prototypes self.bullets = { "/example/flame.goc", "/example/lightning.goc", "/example/rock.goc", } -- the currently used bullet prototype self.bullet_index = 1 -- shoot one bullet per second -- animate the bullet up 1000 pixels and then delete it timer.delay(0.2, true, function() local id = factory.create("#bulletfactory") local to = go.get_position(id) to.y = to.y + 1000 go.animate(id, "position", go.PLAYBACK_ONCE_FORWARD, to, go.EASING_LINEAR, 1.5, 0, function() go.delete(id) end) end) end function on_input(self, action_id, action) -- mouse or spacebar if (action_id == hash("touch") or action_id == hash("key_space")) and action.pressed then -- next bullet prototype, wrap around to the first self.bullet_index = self.bullet_index + 1 if self.bullet_index > #self.bullets then self.bullet_index = 1 end -- unload current prototype factory.unload("#bulletfactory") -- set a new prototype local prototype = self.bullets[self.bullet_index] factory.set_prototype("#bulletfactory", prototype) end end ``` # Shoot bullets {#examples:factory:bullets} This example shows how to dynamically spawn bullet game objects using a factory component. [Project files](https://github.com/defold/examples/tree/master/factory/bullets) This example shows how to dynamically spawn bullet game objects using a factory component and how to also move and delete the bullets. The setup consists of two game objects; one for the player and one for the bullet that is spawned using a factory component. Combine this example with some of the examples from the movement and physics categories to create a shoot 'em up game! player : The red ship at the bottom. Contains: - A *Sprite* component with the spaceship image. - A *Factory* component to spawn bullet game objects - A script to handle spawning of bullets. bullet : The bullet fired by the player. Contains: - A *Sprite* component with a bullet image. ## Scripts ### player.script ```lua function init(self) -- make sure the script will receive user input msg.post(".", "acquire_input_focus") end function on_input(self, action_id, action) -- mouse or spacebar if (action_id == hash("touch") or action_id == hash("key_space")) and action.pressed then -- position bullet somewhat offset from the player position local pos = go.get_position() pos.y = pos.y + 50 -- spawn a bullet local bullet_id = factory.create("#bulletfactory", pos) -- animate the bullet local distance = 1000 -- distance in pixels local speed = 800 -- pixels per second local duration = distance / speed -- time in second to travel the full distance local to = pos.y + distance -- start animation and delete bullet when it has reached its destination go.animate(bullet_id, "position.y", go.PLAYBACK_ONCE_FORWARD, to, go.EASING_LINEAR, duration, 0, function() go.delete(bullet_id) end) end end ``` # Spawn enemies with central management {#examples:factory:spawn_manager} This example shows how to spawn enemy game objects using a factory component and use a central manager to control movement and behavior of all enemies. [Project files](https://github.com/defold/examples/tree/master/factory/spawn_manager) This example shows how to dynamically spawn enemy game objects using a factory component and use a central manager to control movement and behavior of all enemies. The setup consists of three main components: a player ship, enemy spawner, and different enemy types with customizable properties. Press keys `1`, `2`, or `3` to spawn different enemy types. Example collection consists of 2 game objects: ### Ship The red ship at the bottom that automatically moves and shoots. Consists of: - A *Factory* component `bulletfactory` to spawn bullet game objects - A *Script* `ship` that handles automatic movement (ping-pong animation) and bullet spawning every 0.25 seconds - A *Sprite* component with the spaceship image Bullets are simply animated upward and automatically deleted when they reach the top. ### Spawner Controls enemy spawning with keyboard input. Consists of: - A *Factory* `enemyfactory` to spawn enemies with different properties - A *Label* `example_description` with instructions text displayed on top - A *Script* `spawner` that spawns enemies. The spawner script defines three different enemy types: `random`, `diagonal`, and `straight`. Uses a factory to create enemies and store their ids and properties in a look-up table: ```lua local properties = ENEMY_TYPES[enemy_type] local id factory.create("#enemyfactory", position) self.enemies[id] = { ... } ``` The spawner script handles enemy movement by looping over the list of currently spawned enemies in the `update()` lifecycle function. It also uses a physics event listener to detect any enemy to bullet collisions. The spawner script also deletes enemy objects and removes them from the look-up table. ### Enemy Types **Random Enemy** (Key 1): - Green UFO sprite - 1 health point - Random horizontal movement that changes every second - Speed: 40 horizontal, -100 vertical **Diagonal Enemy** (Key 2): - Red enemy sprite - 2 health points - Fixed diagonal movement - Speed: 120 horizontal, -80 vertical **Straight Enemy** (Key 3): - Blue enemy sprite - 3 health points - Straight downward movement - Speed: 0 horizontal, -40 vertical Combine this example with other movement and physics examples to create a complete shoot'em up game! ## Scripts ### ship.script ```lua function init(self) -- Animate automatic player position go.animate(".", "position.x", go.PLAYBACK_LOOP_PINGPONG, 620, go.EASING_LINEAR, 6.0) -- Create a timer to tick every 0.25 second: timer.delay(0.25, true, function() -- Create a simple bullet bullet using the factory local bullet_id = factory.create("#bulletfactory", go.get_position()) -- Animate the created bullet towards top of screen, where it is deleted if bullet_id then go.animate(bullet_id, "position.y", go.PLAYBACK_ONCE_FORWARD, 600, go.EASING_LINEAR, 1, 0, function() go.delete(bullet_id) end) end end) end ``` ### spawner.script ```lua -- Pre-hash some strings string since they will be used a lot local TRIGGER_EVENT = hash("trigger_event") local GROUP_BULLET = hash("bullet") local GROUP_ENEMY = hash("enemy") -- Define different properties for different enemies: local ENEMY_TYPES = { random = { sprite = hash("ufoGreen"), health_points = 1, speed = vmath.vector3(40, -100, 0), is_random = true }, diagonal = { sprite = hash("enemyRed2"), health_points = 2, speed = vmath.vector3(120, -80, 0), is_random = false }, straight = { sprite = hash("enemyBlue4"), health_points = 3, speed = vmath.vector3(0, -40, 0), is_random = false } } -- Helper function to spawn given enemy by its type: local function spawn_enemy(self, enemy_type) -- Select properties of the enemy by type: local properties = ENEMY_TYPES[enemy_type] -- Set initial position of the spawned ship. local position = go.get_position() -- This will make the position one out of (-180, -90, 0, 90, 180): position.x = position.x + math.random(-2,2) * 90 -- create enemy local id = factory.create("#enemyfactory", position) -- set animation of the sprite to the one defined by enemy properties local sprite_url = msg.url(nil, id, "sprite") sprite.play_flipbook(sprite_url, properties.sprite) -- Add randomness to horizontal direction - this way enemy horizontal speed may be inverted or cleared: -- -1 * self.speed.x - inverted direction -- 0 * self.speed.x - cleared direction -- 1 * self.speed.x - regular direction local speed = vmath.vector3(properties.speed) speed.x = speed.x * math.random(-1, 1) -- store enemy self.enemies[id] = { id = id, health = properties.health_points, speed = speed, is_random = properties.is_random, timer = 1 } end function init(self) -- Acquire input focus here, so we can handle inputs: msg.post(".", "acquire_input_focus") self.enemies = {} -- listen to physics events -- in this case we care about trigger events between -- enemies and bullets physics.set_event_listener(function(self, events) for _,event in ipairs(events) do local event_type = event.type if event_type == TRIGGER_EVENT then -- get the bullet id and enemy id if the colliding objects belong to -- groups "bullet" and "enemy" -- this is the Lua way of writing a ternary operator local bullet_id = (event.a.group == GROUP_BULLET and event.a.id) or (event.b.group == GROUP_BULLET and event.b.id) local enemy_id = (event.a.group == GROUP_ENEMY and event.a.id) or (event.b.group == GROUP_ENEMY and event.b.id) -- not really necessary in this example but we might as well -- double-check that the detected collision was for a bullet and enemy if bullet_id and enemy_id then -- remove the bullet go.delete(bullet_id) -- get the enemy from the managed enemies list local enemy = self.enemies[enemy_id] -- Remove one health point enemy.health = enemy.health - 1 -- When no health points left - remove this ship if enemy.health == 0 then go.delete(enemy_id) self.enemies[enemy_id] = nil -- Play particlefx for damage taken: particlefx.play(msg.url(nil, enemy_id, "boom")) end end end end end) end function update(self, dt) for id,enemy in pairs(self.enemies) do -- Update enemy position based on its current speed: local pos = go.get_position(id) pos = pos + enemy.speed * dt go.set_position(pos, id) -- Bounce enemy off "walls": if pos.x > 600 or pos.x < 50 then enemy.speed.x = -enemy.speed.x end -- Remove enemy if it goes out of screen: if pos.y < -50 then go.delete(id) self.enemies[id] = nil end -- If enemy has random movement decrease timer to -- randomly switch horizontal speed every second if enemy.is_random then enemy.timer = enemy.timer - dt if enemy.timer < 0 then enemy.timer = enemy.timer + 1 enemy.speed.x = math.random(-1, 1) * enemy.speed.x end end end end function on_input(self, action_id, action) -- React to different key presses with spawning different enemies: if action_id == hash("key_1") and action.released then spawn_enemy(self, "random") elseif action_id == hash("key_2") and action.released then spawn_enemy(self, "diagonal") elseif action_id == hash("key_3") and action.released then spawn_enemy(self, "straight") end end ``` # Spawn enemies with script properties {#examples:factory:spawn_properties} This example shows how to spawn enemy game objects using a factory component with different properties. [Project files](https://github.com/defold/examples/tree/master/factory/spawn_properties) This example shows how to dynamically spawn enemy game objects using a factory component with different properties. The setup consists of three main components: a player ship, enemy spawner, and different enemy types with customizable properties. Press keys `1`, `2`, or `3` to spawn different enemy types. Example collection consists of 2 game objects: ### Ship The red ship at the bottom that automatically moves and shoots. Consists of: - A *Factory* component `bulletfactory` to spawn bullet game objects - A *Script* `ship` that handles automatic movement (ping-pong animation) and bullet spawning every 0.25 seconds - A *Sprite* component with the spaceship image Bullets are simply animated upward and automatically deleted when they reach the top. ### Spawner Controls enemy spawning with keyboard input. Consists of: - A *Factory* `enemyfactory` to spawn enemies with different properties - A *Label* `example_description` with instructions text displayed on top - A *Script* `spawner` that spawns enemies. The spawner script defines three different enemy types: `random`, `diagonal`, and `straight`. Uses factory to create enemies with specific properties: ```lua local properties = ENEMY_TYPES[enemy_type] factory.create("#enemyfactory", position, nil, properties) ``` ### Enemy Types **Random Enemy** (Key 1): - Green UFO sprite - 1 health point - Random horizontal movement that changes every second - Speed: 40 horizontal, -100 vertical **Diagonal Enemy** (Key 2): - Red enemy sprite - 2 health points - Fixed diagonal movement - Speed: 120 horizontal, -80 vertical **Straight Enemy** (Key 3): - Blue enemy sprite - 3 health points - Straight downward movement - Speed: 0 horizontal, -40 vertical ### Enemy Script Properties Properties defined in `enemy.script` control enemy behavior: - `sprite` - Which sprite to display - `health_points` - How many hits before destruction - `speed` - Movement velocity vector - `is_random` - Whether to use random movement changes When enemies have `go.property` defined in their script, these properties are visible in the *Properties* pane and can be customized per enemy type. Combine this example with other movement and physics examples to create a complete shoot'em up game! ## Scripts ### ship.script ```lua function init(self) -- Animate automatic player position go.animate(".", "position.x", go.PLAYBACK_LOOP_PINGPONG, 620, go.EASING_LINEAR, 6.0) -- Create a timer to tick every 0.25 second: timer.delay(0.25, true, function() -- Create a simple bullet bullet using the factory local bullet_id = factory.create("#bulletfactory", go.get_position()) -- Animate the created bullet towards top of screen, where it is deleted if bullet_id then go.animate(bullet_id, "position.y", go.PLAYBACK_ONCE_FORWARD, 600, go.EASING_LINEAR, 1, 0, function() go.delete(bullet_id) end) end end) end ``` ### enemy.script ```lua -- Define different properties of the script: go.property("sprite", hash("ufoGreen")) go.property("health_points", 1) go.property("speed", vmath.vector3(100, 100, 0)) go.property("is_random", true) function init(self) -- Set animation of the sprite to the one defined by its property self.sprite: sprite.play_flipbook("#sprite", self.sprite) -- Add randomness to horizontal direction - this way enemy horizontal speed may be inverted or cleared: -- -1 * self.speed.x - inverted direction -- 0 * self.speed.x - cleared direction -- 1 * self.speed.x - regular direction self.speed.x = math.random(-1, 1) * self.speed.x -- If self.is_random boolean property is true: if self.is_random then -- add a timer to randomly switch horizontal speed every second: timer.delay(1, true, function() self.speed.x = math.random(-1, 1) * self.speed.x end) end end function update(self, dt) -- Update enemy position based on its current speed: local pos = go.get_position() pos = pos + self.speed * dt go.set_position(pos) -- Bounce enemy off "walls": if pos.x > 600 or pos.x < 50 then self.speed.x = -self.speed.x end -- Remove enemy if it goes out of screen: if pos.y < -50 then go.delete() end end function on_message(self, message_id, message, sender) -- React to collision with bullet: if message_id == hash("trigger_response") and message.enter then -- Remove one health point self.health_points = self.health_points - 1 -- Play particlefx for damage taken: particlefx.play("#boom") -- When no health points left - remove this ship if self.health_points <= 0 then go.delete() end end end ``` ### spawner.script ```lua -- Define different properties for different enemies: local ENEMY_TYPES = { random = { sprite = hash("ufoGreen"), health_points = 1, speed = vmath.vector3(40, -100, 0), is_random = true }, diagonal = { sprite = hash("enemyRed2"), health_points = 2, speed = vmath.vector3(120, -80, 0), is_random = false }, straight = { sprite = hash("enemyBlue4"), health_points = 3, speed = vmath.vector3(0, -40, 0), is_random = false } } function init(self) -- Acquire input focus here, so we can handle inputs: msg.post(".", "acquire_input_focus") end -- Helper function to spawn given enemy by its type: local function spawn_enemy(enemy_type) -- Select properties of the enemy by type: local properties = ENEMY_TYPES[enemy_type] -- Set initial position of the spawned ship. local position = go.get_position() -- This will make the position one out of (-180, -90, 0, 90, 180): position.x = position.x + math.random(-2,2) * 90 -- Create enemy with passed properties factory.create("#enemyfactory", position, nil, properties) end function on_input(self, action_id, action) -- React to different key presses with spawning different enemies: if action_id == hash("key_1") and action.released then spawn_enemy("random") elseif action_id == hash("key_2") and action.released then spawn_enemy("diagonal") elseif action_id == hash("key_3") and action.released then spawn_enemy("straight") end end ``` # Spawn game object {#examples:factory:basic} This example shows how to dynamically spawn game objects with a factory component. [Project files](https://github.com/defold/examples/tree/master/factory/basic) The "debrisfactory" factory component uses the file *debris.go* as prototype, meaning that it produces game objects that are all copies of that file. ## Scripts ### bunny.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> end function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed then -- <2> local pos = vmath.vector3(action.x, action.y, 0) -- <3> local carrot_id = factory.create("#carrotfactory", pos) -- <4> go.animate(carrot_id, "euler.z", go.PLAYBACK_ONCE_FORWARD, 360, go.EASING_LINEAR, 1, 0, function() -- <5> go.delete(carrot_id) -- <6> end) end end --[[ 1. Acquire input focus so we get input from the engine. 2. If the user clicks. 3. Set the spawning position to the mouse click position. 4. Tell the component "carrotfactory" ("#" denotes a component in the current game object) to spawn a game object according to its prototype. The function returns the id of the new game object. 5. Rotate the new game object. 6. Delete the game object --]] ``` ### debris.script ```lua function init(self) self.t = 2 -- <1> end function update(self, dt) self.t = self.t - dt -- <2> if self.t < 0 then go.delete() -- <3> end end --[[ 1. Store a value `t` in the current script component (`self`). 2. Decrease `t` with delta time (elapsed since last call to `update()`). 3. If `t` is below 0, delete the current game object ("." is shorthand for that). --]] ``` # Load JSON data {#examples:file:json_load} This example shows how to load json data using sys.load_resource(). [Project files](https://github.com/defold/examples/tree/master/file/json_load) The example will load a json file. This can be useful for something like level data. Before we can load a resource we need to tell Defold that we have custom resources. We do this by changing the "custom resources" entry within our game.project file. ## Scripts ### json_load.script ```lua local function load_level(level_name) local level_path = "/levels/" .. level_name .. ".json" -- <1> local data = sys.load_resource(level_path) -- <2> local json_data = json.decode(data) -- <3> label.set_text("#title", json_data.title) -- <4> end function init(self) msg.post(".", "acquire_input_focus") end function on_input(self, action_id, action) if action_id == hash("key_1") then if action.released then load_level("level_001") end elseif action_id == hash("key_2") then if action.released then load_level("level_002") end end end --[[ 1. Convinience sake we only want pass in the name of the level, but to load the resource we need to give it the full path. 2. Load the resource, this will return a string. 3. Use the json.decode to make our string into a lua table. 4. Use the loaded level data in whatever way we want. --]] ``` # Save and Load {#examples:file:sys_save_load} This example shows how to save and load data using sys.save() and sys.load() [Project files](https://github.com/defold/examples/tree/master/file/sys_save_load) The example will save and load a file containing a Lua table with a single value key-value pair representing a highscore. Loading and saving is done using sys.load() and sys.save(). Also refer to the [Working with files manual](https://defold.com/manuals/file-access/). ## Scripts ### sys_save_load.script ```lua local function load_highscore() local filename = sys.get_save_file("sys_save_load", "highscore") -- <1> local data = sys.load(filename) -- <2> return data.highscore or 0 -- <3> end local function save_highscore(highscore) local filename = sys.get_save_file("sys_save_load", "highscore") sys.save(filename, { highscore = highscore }) -- <4> end local function update_labels(score, highscore) label.set_text("score#score", tostring(score)) label.set_text("score#highscore", "HIGH SCORE\n" .. tostring(highscore)) end function init(self) msg.post(".", "acquire_input_focus") self.score = 0 self.highscore = load_highscore() update_labels(self.score, self.highscore) end function update(self, dt) if self.pressed then self.score = self.score + math.ceil(100 * dt) update_labels(self.score, self.highscore) end end function on_input(self, action_id, action) if action_id == hash("touch") then if action.pressed then self.score = 0 self.pressed = true elseif action.released then self.pressed = false if self.score > self.highscore then self.highscore = self.score save_highscore(self.highscore) update_labels(self.score, self.highscore) end end end end --[[ 1. Get an application specific path for the file "highscore" 2. Load saved data. 3. The returned data is a Lua table with the saved values or an empty table if nothing has been saved. 4. Save data. The data to save must be stored in a Lua table. --]] ``` # Button {#examples:gui:button} A GUI box node with an image texture and a script to make it act as a button. [Project files](https://github.com/defold/examples/tree/master/gui/button) The "gui" game object contains a GUI component stored in the file *button.gui*. The GUI contains the setup with the "button" box node for the button image and the "text" text node for the button label text. *button.gui* has a script attached to it, called *button.gui_script*, which contains the button logic. ## Scripts ### button.gui_script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> end function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed then -- <2> local button = gui.get_node("button") -- <3> local text = gui.get_node("text") -- <4> if gui.pick_node(button, action.x, action.y) then -- <5> gui.set_text(text, "HELLO!") -- <6> else gui.set_text(text, "CLICK ME!") -- <7> end end end --[[ 1. Tell the engine that this game object wants to receive input. 2. If the user clicks. 3. Get the instance for the node named "button" (the button box). 4. Get the instance for the node named "text" (the button label). 5. Check if the click position (`action.x` and `action.y`) is within the boundaries of the button node. 6. If the user clicks on the button, change the label text. 7. If the user clicks elsewhere, change the label text to something else. --]] ``` # Drag {#examples:gui:drag} This example shows how to drag a GUI box node. [Project files](https://github.com/defold/examples/tree/master/gui/drag) This example shows how to drag a GUI box node. The example has a list of box nodes that can be dragged. It uses `gui.pick_node()` to detect if a click is within the bounds of a box and then moves the box as long as the mouse button is pressed. ## Scripts ### drag.gui_script ```lua function init(self) msg.post(".", "acquire_input_focus") -- list of boxes to drag self.boxes = { gui.get_node("box1"), gui.get_node("box2"), gui.get_node("box3"), } -- variable where the currently dragged box is stored self.dragged_box = nil end function on_input(self, action_id, action) if action_id == hash("touch") then -- update the position of the currently dragged box if self.dragged_box then local mouse_position = vmath.vector3(action.x, action.y, 0) gui.set_position(self.dragged_box, mouse_position) end -- check if the mouse button was pressed if action.pressed then -- iterate the list of boxes and check if the mouse was -- clicked on a box for i=1,#self.boxes do local box = self.boxes[i] -- this will return true if the x and y is within the -- bounds of the box if gui.pick_node(box, action.x, action.y) then -- keep track of the box as being dragged self.dragged_box = box break end end -- check if the mouse button was released -- clear the variable which keeps track of which box is dragged elseif action.released then self.dragged_box = nil end end end ``` # Get and set a gui font resource {#examples:gui:get_set_font} This example shows how to get and set a font resource on a gui component. [Project files](https://github.com/defold/examples/tree/master/gui/get_set_font) ## Scripts ### get_set_font.script ```lua -- create a script resource property 'myfont' referencing a font file go.property("myfont", resource.font("/assets/text48.font")) function init(self) msg.post(".", "acquire_input_focus") -- get the font file on the gui component which is assigned to -- the font with id 'default' self.default_font = go.get("#gui", "fonts", { key = "default" }) end function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed then -- get the font file currently assigned to the font with id 'default' local current_font = go.get("#gui", "fonts", { key = "default" }) -- toggle between the default font and the font referenced by the -- script resource property 'myfont' if current_font == self.myfont then go.set("#gui", "fonts", self.default_font, { key = "default" }) else go.set("#gui", "fonts", self.myfont, { key = "default" }) end end end ``` # Get and set a gui material resource {#examples:gui:get_set_material} This example shows how to get and set a material resource on a gui component. [Project files](https://github.com/defold/examples/tree/master/gui/get_set_material) ## Scripts ### get_set_material.script ```lua -- create a script resource property 'myfont' referencing a font file go.property("mymaterial", resource.material("/example/get_set_material.material")) function init(self) msg.post(".", "acquire_input_focus") -- get the material file on the gui component which is assigned to -- the material with id 'default' self.default_texture = go.get("#gui", "materials", { key = "default" }) end function on_input(self, action_id, action) if action_id == hash("mouse_button_left") and action.pressed then -- get the material file currently assigned to the material with id 'default' local current_texture = go.get("#gui", "materials", { key = "default" }) -- toggle between the default material and the material referenced by the -- script resource property 'default' if current_texture == self.mymaterial then go.set("#gui", "materials", self.default_texture, { key = "default" }) else go.set("#gui", "materials", self.mymaterial, { key = "default" }) end end end ``` # Get and set a gui texture resource {#examples:gui:get_set_texture} This example shows how to get and set a texture resource on a gui component. [Project files](https://github.com/defold/examples/tree/master/gui/get_set_texture) ## Scripts ### get_set_texture.script ```lua -- create a script resource property 'myatlas' referencing an atlas file go.property("myatlas", resource.atlas("/example/get_set_texture.atlas")) function init(self) msg.post(".", "acquire_input_focus") -- get the atlas file on the gui component which is assigned to -- the atlas/texture with id 'ui' self.default_atlas = go.get("#gui", "textures", { key = "ui" }) end function on_input(self, action_id, action) if action_id == hash("mouse_button_left") and action.pressed then -- get the atlas file currently assigned to the atlas/texture with id 'ui' local current_atlas = go.get("#gui", "textures", { key = "ui" }) -- toggle between the default texture and the texture referenced by the -- script resource property 'ui' if current_atlas == self.myatlas then go.set("#gui", "textures", self.default_atlas, { key = "ui" }) else go.set("#gui", "textures", self.myatlas, { key = "ui" }) end end end ``` # GUI color {#examples:gui:color} This example shows how change the color of GUI nodes at run-time [Project files](https://github.com/defold/examples/tree/master/gui/color) The example shows how to change the color of GUI nodes using `gui.set_color()` and `gui.animate()`. Nodes will normally inherit the alpha of parent nodes, unless the Inherit Alpha checkbox is unchecked. ## Scripts ### color.gui_script ```lua function init(self) gui.animate(gui.get_node("logo1"), gui.PROP_COLOR, vmath.vector4(1, 0, 0, 1), gui.EASING_INOUTQUAD, 3, 0, nil, gui.PLAYBACK_LOOP_PINGPONG) -- <1> gui.animate(gui.get_node("logo2"), "color.x", 0, gui.EASING_INOUTQUAD, 3, 0, nil, gui.PLAYBACK_LOOP_PINGPONG) -- <2> gui.animate(gui.get_node("bg"), "color.w", 0, gui.EASING_INOUTQUAD, 4, 0, nil, gui.PLAYBACK_LOOP_PINGPONG) -- <3> gui.set_color(gui.get_node("logo3"), vmath.vector4(1, 0, 0, 1)) -- <4> end --[[ 1. x,y,z,w -> r,g,b,a. Keep read and alpha. Animate green and blue to 0. 2. x = red. Animate the red color component to 0. 3. w = alpha. Animate the alpha color component to 0. All children which inherit alpha will be affected. 4. Set the color of the node. --]] ``` # GUI progress indicators {#examples:gui:progress} This example shows how to create various types of progress indicators [Project files](https://github.com/defold/examples/tree/master/gui/progress) The example shows three different types of progress indicators: 1. A horizontal progress bar created using a box node with a texture and 9-slice scaling 2. A numerical progress text created using a text node 3. A circular progress created using a pie node ## Scripts ### progress.gui_script ```lua -- set the width of the horizontal progress bar local function update_horizontal(p) local node = gui.get_node("horizontal") local size = gui.get_size(node) size.x = p * 400 -- max width is 400 pixel gui.set_size(node, size) end -- set value of numeric progress indicator (in percent from 0% to 100%) local function update_numeric(p) local node = gui.get_node("numeric") local percent = math.floor(p * 100) gui.set_text(node, tostring(percent) .. "%") end -- update radial/circle progress by changing the fill angle local function update_radial(p) local node = gui.get_node("radial") local angle = p * 360 -- full circle is 360 degrees gui.set_fill_angle(node, angle) end function init(self) self.time = 0 end function update(self, dt) self.time = self.time + dt -- calculate a value between 0.0 and 1.0 -- the value will gradually increas from 0 to 1 during 3 seconds local p = (self.time % 3) / 3 update_numeric(p) update_horizontal(p) update_radial(p) end ``` # Health Bar {#examples:gui:healthbar} This example demonstrates how to add different health bars. [Project files](https://github.com/defold/examples/tree/master/gui/healthbar) Overview : Example shows 3 pairs of nodes each forming a "health bar" with different pivots. Create a pair of Box nodes, so that child node is smaller than the parent: Example contains 3 such pairs - each with different `Pivot` and `X Anchor` settings for inner health bars: - `West` + `Left` - `East` + `Right` - `Center` + `None` Health is indicated as the size on X Axis of the inner node, so define what can be maximum and minimum width here. Create a collection with such GUI component and add it and your game object with script to collection: Example shows communication between `controller#main` script component (`healthbar.script`) and `hud#main` gui component with gui_script (`healthbar.gui_script`). ## Scripts ### healthbar.script ```lua function init(self) -- < 1 > self.player_one_health = 1.0 self.player_two_health = 1.0 self.game_boss_health = 1.0 -- < 2 > timer.delay(1, true, function() -- < 3 > self.player_one_health = math.max(self.player_one_health - 0.1, 0) self.player_two_health = math.max(self.player_two_health - 0.1, 0) self.game_boss_health = math.max(self.game_boss_health - 0.1, 0) -- < 4 > msg.post("hud", "update_health", { health_name = "left_health", health_percentage = self.player_one_health }) msg.post("hud", "update_health", { health_name = "right_health", health_percentage = self.player_two_health }) msg.post("hud", "update_health", { health_name = "center_health", health_percentage = self.game_boss_health }) end) end --[[ 1. Set initial health percentage (1.0 = 100%, 0.0 = 0%). 2. Start a timer that will call every 1 second (first argument) repeateadly (second argument being true) a callback function (3rd argument) 3. Reduce each health percentage by 0.1 (10%), but no less than 0 (using math.max to select `0`, if `self.player_one_health - 0.1` is less than `0`). 4. Send messages to hud (gui component) to "updated_health" with health name and percentage to be set in GUI script. ]] ``` ### healthbar.gui_script ```lua -- < 1 > local min_size = 48 local max_size = 235 - min_size -- < 2 > local function set_healthbar(healthbar_node_name, health_percentage) local healthbar_node = gui.get_node(healthbar_node_name) -- < 3 > local healthbar_size = gui.get_size(healthbar_node) -- < 4 > healthbar_size.x = health_percentage * max_size + min_size -- < 5 > gui.set_size(healthbar_node, healthbar_size) -- < 6 > end function init(self) -- < 7 > set_healthbar("left_health", 1.0) set_healthbar("right_health", 1.0) set_healthbar("center_health", 1.0) end function on_message(self, message_id, message, sender) -- < 8 > if message_id == hash("update_health") then set_healthbar(message.health_name, message.health_percentage) end end --[[ 1. Define minimum and maximum size of GUI healthbar (only width is changed). 2. Define a local helper function to update healthbar. 3. Get node of given name passed as "healthbar_node_name" and store it in local variable "healthbar_node". 4. Get size of this node and store it in local variable "healthbar_size". 5. Change size along X axis (width) of the node to given "health_percentage" scaled times "max_size" and added to "min_size", so that it can be no smaller than it. 6. Set the newly updated size of the node. 7. In init function, for each of three defined nodes set initial health_percentage to 1.0 (100%). 8. In on_message function, if the GUI component receives message "update_health" call helper function to update given health bar. ]] ``` # Layouts {#examples:gui:layouts} This example demonstrates the use of layouts. [Project files](https://github.com/defold/examples/tree/master/gui/layouts) Overview : A small UI panel that changes its position depending on the screen size (canvas size in HTML5) using the Defold layouts system. [:More on Layouts with Defold:](https://defold.com/manuals/gui-layouts/#layouts) Layouts are added in the GUI where we want to support them: The panel is configured in both layouts, Portrait and Landscape: ## Scripts ### layouts.gui_script ```lua local function set_scores_state(self, score_state) gui.set_text(self.ui_elements.num_score, score_state.score) gui.set_text(self.ui_elements.num_best, score_state.best_score) end function init(self) self.current_score_state = { -- < 1 > score = math.random(100, 500), best_score = math.random(501, 999) } self.ui_elements = {} -- < 2 > self.ui_elements.num_score = gui.get_node("num_score") self.ui_elements.num_best = gui.get_node("num_best") set_scores_state(self, self.current_score_state) -- < 3 > end function on_message(self, message_id, message, sender) if message_id == hash("layout_changed") then -- < 4 > set_scores_state(self, self.current_score_state) elseif message_id == hash("update_score") then -- < 5 > self.current_score_state.score = self.current_score_state.score + message.score if self.current_score_state.score > self.current_score_state.best_score then self.current_score_state.best_score = self.current_score_state.score end set_scores_state(self, self.current_score_state) end end --[[ 1.-It's important to store the state of the UI separately from the view. 2.-Having all the nodes for UI elements makes it easier to work with. 3.-This function updates the view with the current state. 4.-When the layout changes, all the nodes (view) reset to the corresponding layout setup. At this point, we need to restore our state. 5.-External code updates the state, and we apply changes of the state to the view. --]] ``` # Load texture {#examples:gui:load_texture} This example shows how to load and set a dynamic texture on a gui box node. [Project files](https://github.com/defold/examples/tree/master/gui/load_texture) The "gui" game object contains a GUI component stored in the file *load_texture.gui*. The GUI contains the setup with the "button" box node for the button image, the "text" text node for the button label text and the "img" box node for loaded images. *load_texture.gui* has a script attached to it, called *load_texture.gui_script*, which contains the button logic and logic for loading images. ## Scripts ### load_texture.gui_script ```lua local function set_message(text) gui.set_text(gui.get_node("message"), text) -- <11> end local function set_image(self, texture_id, image_data) if self.texture_id then -- <8> gui.delete_texture(self.texture_id) self.texture_id = nil end local img = image.load(image_data) -- <9> if not img then set_message("Unable to load image") return end if gui.new_texture(texture_id, img.width, img.height, img.type, img.buffer) then -- <10> self.texture_id = texture_id -- <11> gui.set_texture(gui.get_node("img"), texture_id) -- <12> set_message("Set new texture") else set_message("Unable to create texture") end end local load_image load_image = function(url) http.request(url, "GET", function(self, id, res) -- <6> -- redirect? if res.status == 302 or res.status == 301 then -- <7> set_message("Redirect: " .. res.headers.location) load_image(res.headers.location) -- ok or cached? elseif res.status == 200 or res.status == 304 then -- <7> set_image(self, url, res.response) -- error else set_message("Unable to get image: " .. res.response) end end) end local function load_random(self) local url = "https://picsum.photos/id/"..math.random(1, 10).."/200/300.jpg" -- <3> set_message("Loading...") -- <4> load_image(url) -- <5> end function init(self) msg.post(".", "acquire_input_focus") -- <1> load_random(self) -- <2> end function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed then if gui.pick_node(gui.get_node("button"), action.x, action.y) then -- <13> load_random(self) -- <2> end end end --[[ 1. Tell the engine that this game object wants to receive input. 2. Start loading random image 3. Generate a URL to a random image 4. Change the label text. 5. Call function load image from URL 6. Make an HTTP request and handle redirects 7. Check server response 8. Remove previous texture if any 9. Create an image resource from loaded image data 10. Create a new texture using image resource 11. Save the texture id 12. Set new texture as node texture 13. Check if the click position (`action.x` and `action.y`) is within the boundaries of the button node. --]] ``` # Localization (RTL/LTR) {#examples:gui:localization} This example demonstrates how to handle localization in games, Unicode text layout, RTL rendering, and runtime font switching for localization. [Project files](https://github.com/defold/examples/tree/master/gui/localization) This example demonstrates how to handle localization in games, Unicode text layout, RTL rendering, and runtime font switching for localization. Click the buttons (EN, AR, PT, JA) to switch between 4 languages. Arabic demonstrates right-to-left layout, while English/Portuguese/Japanese show left-to-right layout. ## Approach overview The example is intentionally modularized and the flow in the program is linear: 1. Read localized strings from a JSON file for the requested language. 2. If the language needs a non-default font, load the font collection proxy asynchronously. 3. Attach the font at runtime to the default GUI font resource. 4. Prewarm glyphs for the requested text so the first render is smooth. 5. Update the GUI text and layout (LTR/RTL) and restore input focus. This illustrates a practical localization flow in Defold: - Runtime font switching via `font.add_font()` / `font.remove_font()`. - Asynchronous proxy loading for large font resources. - Glyph prewarming with `font.prewarm_text()`. - LTR/RTL layout using text node pivot and position. To recreate such an example: 1. Add to your project an [App Manifest](https://defold.com/manuals/app-manifest/) file with the option `Use full font layout system` enabled. The rest of the settings doesn't matter for this example, so are left as default. 2. Use this App Manifest file in the `game.project` file in the `Native Extension` section in the `App Manifest` setting. 3. Then, also in the `game.project` file in the `Font` section enable the `Runtime Generation` setting. 4. In the end, add the localization of the used JSON files in the `Project` section in the `Custom Resources` setting. Project setup used by this example: - `game.project` with runtime font generation enabled and custom app manifest `main.appmanifest`. - `main.collection` with: - game object `go` with: - `ar_proxy` - collection proxy component referring to `lang_ar.collection` file. - `ja_proxy` - collection proxy component referring to `lang_ja.collection` file. - `main.gui` - GUI component with `main.gui_script`. The 2 mentioned collections (`lang_ar.collection` / `lang_ja.collection`) contain: - `go` game object with: - `label` - component with `Font` property set to `noto_ar.font`/`noto_ja.font` In the `assets` folder there are two subfolders: - `fonts` - containing `.ttf` font files and `.font` Defold resources referencing those font files respectively - `img` - containing images and atlas used for GUI nodes. - `texts` - containing `.json` files with text examples and information about language used. The separate Collections for components with fonts and Collection Proxies to load and unload them are added to show good practices on handling fonts - usually, you only need the one font that user selected in the settings, so rest of the fonts should be unloaded from memory. Therefore, we have in the example only one font that is defined in the GUI component, that is `latin`. The rest (Arabic `noto_ar` and Japanese `noto_ja`) are loaded using respective Collection Proxy components `ar_proxy` and `ja_proxy`. Those collections contain the game object with component in order to assign there a Font resource - `noto_ar` and `noto_ja`. A [Collection Proxy](https://defold.com/manuals/collection-proxy/) in Defold is a special component that allows you to load and unload entire collections (groups of game objects, components and resources) dynamically at runtime. In this example, proxies are used to manage fonts, so that only the font needed by the user is kept in memory at any time. ### How are proxies loaded and unloaded? 1. **Loading a proxy:** - When the user clicks a language button (like "AR" or "JA"), the script checks if that language requires a special font. - If so, it determines which proxy to use (`ar_proxy` for Arabic, `ja_proxy` for Japanese, etc.). - The script sends the `async_load` message to the appropriate proxy, and Defold begins loading the target collection (`lang_ar.collection`, `lang_ja.collection`, etc.) asynchronously. - Once the collection is loaded, the related assets (mainly the font resource) are available in RAM. - The script receives a `proxy_loaded` message, and can now activate the font for GUI text. 2. **Unloading a proxy:** - When the user switches to another language that uses a different font (or goes back to a language using the default font), the no-longer-needed proxy should be unloaded. - The script sends the `unload` message to the relevant proxy. - After unloading, Defold automatically releases all resources from that collection—freeing the memory taken by the font and any related resources. - Once unloading is finished, the script receives a `proxy_unloaded` message and may proceed to load or activate the next font as needed. ### How are these collections (`lang_ar.collection`, `lang_ja.collection`) constructed? - Each collection contains just a single game object with an empty label (or text) component. - This component is configured to use the specific font file needed for that language (e.g., a TTF that supports Arabic or Japanese.) - No additional game logic or nodes are needed inside—these collections simply act as packages for the required font resource. This structure is a Defold best practice: the font is only referenced as long as the proxy is loaded. When the proxy is unloaded, Defold can fully release the font and its memory, keeping the application efficient. This is important for games with large multilingual font files; only the currently active font consumes RAM, even when switching languages at runtime. The localized text strings are loaded from disk (`text_en.json`, `text_ar.json`, `text_pt.json`, `text_ja.json`) using `sys.load_resource()`. ## Helper modules The logic is split into two small helpers to keep the GUI script concise and focused on flow: - `localization_helper.lua`: Handles the language switch flow (load/unload proxies, attach runtime fonts, prewarm glyphs, finalize switch). It owns the small state machine around proxies and fonts and exposes a simple API to the GUI script. - `ui_helper.lua`: Handles GUI node lookup, button states and visuals, LTR/RTL layout changes, and input handling details. It keeps GUI operations in one place so the core localization logic stays easy to follow. ## Assumptions and simplifications This example intentionally trades robustness for clarity: - Sequential flow only. It assumes one language switch at a time (unload old font, then load new font, then update UI). Because of this, `on_message` does not verify which proxy sent `proxy_loaded` / `proxy_unloaded`. - No JSON caching. The JSON is small and read on demand via `sys.load_resource()` and `json.decode()`. For larger or frequent loads, caching should be demonstrated in a separate example. - Data is trusted. The `languages` table is assumed to be correct and complete (including `json`, `layout`, `proxy`, and `ttf_hash` where required). The JSON is assumed to contain the expected fields (`title`, `text`). - Minimal defensive checks. Assertions and guards are kept light to avoid clutter. These choices keep the example readable and focused on the key idea. ## Scripts ### main.gui_script ```lua -- Helper module for UI operations -- Separated in order not to clutter the example. local ui = require "example.ui_helper" -- Helper module for localization operations local loc = require "example.localization_helper" function init(self) -- Per-language content path, layout (LTR/RTL), -- and an optional proxy with font resource to load, -- and a True Type Font (TTF) file pre-hashed path. self.languages = { en = { json = "/assets/texts/text_en.json", layout = ui.layout.ltr, proxy = false, }, ar = { json = "/assets/texts/text_ar.json", layout = ui.layout.rtl, proxy = "#ar_proxy", ttf_hash = hash("/assets/fonts/NotoSansArabic-Medium.ttf"), }, pt = { json = "/assets/texts/text_pt.json", layout = ui.layout.ltr, proxy = false, }, ja = { json = "/assets/texts/text_ja.json", layout = ui.layout.ltr, proxy = "#ja_proxy", ttf_hash = hash("/assets/fonts/NotoSansJP-Regular.ttf"), }, } -- We delegate UI handling to a separate helper module -- in order not to clutter the example. ui.initialize_ui(self) -- Store the font resource of the default font -- that is initally used for the text gui node. self.default_font_resource = ui.get_font_resource(self.text_node) -- Set the GUI initial current language. self.current_lang = "en" -- Set the initial requested language to the same one. self.requested_lang = "en" -- Get the text for the requested language from the JSON file. self.requested_text = loc.get_content_from_json(self) -- Clear texts and update after fonts are prewarmed. ui.clear_text_nodes(self) loc.finish_language_change(self, ui.update_ui_content_callback) end -- Pre-hashed message IDs. local msg_proxy_loaded = hash("proxy_loaded") local msg_proxy_unloaded = hash("proxy_unloaded") function on_message(self, message_id, message, sender) -- React to proxy lifecycle messages and continue pending language switch. if message_id == msg_proxy_unloaded then -- Remove runtime font once its owning proxy is unloaded. font.remove_font(self.default_font_resource, self.languages[self.current_lang].ttf_hash) -- If old font resource was unloaded, load the new one (or finish with default). if self.languages[self.requested_lang].proxy then msg.post(self.languages[self.requested_lang].proxy, "async_load") else loc.finish_language_change(self, ui.update_ui_content_callback) end elseif message_id == msg_proxy_loaded then loc.finish_language_change(self, ui.update_ui_content_callback) end end -- Pre-hashed action ID. local action_touch = hash("touch") function on_input(self, action_id, action) -- Pointer move arrives with nil action_id in Defold. if action_id == nil and action.x and action.y then ui.on_pointer_moved(self, action.x, action.y) end -- If the action is not a touch: if action_id ~= action_touch then -- Skip the rest of the input handling. return end -- If the action is a touch and pressed: if action.pressed then -- Get the selected language on pressed. local selected_language = ui.get_selected_language_on_pressed(self, action.x, action.y) -- Set the requested language and text. self.requested_lang = selected_language or self.requested_lang -- If the requested language is different from the current language: if self.requested_lang ~= self.current_lang then -- Clear current texts while the new font is prepared. ui.clear_text_nodes(self) -- Get the text for the requested language from the JSON file. self.requested_text = loc.get_content_from_json(self) end -- Process the language change. loc.process_language_change(self, ui.update_ui_content_callback) end -- If the action is a touch and released: if action.released then -- Handle the touch released event. ui.on_touch_released(self, action.x, action.y) end end ``` # Pointer over {#examples:gui:pointer_over} A GUI box node with an image texture and a script that react when pointer over this node. [Project files](https://github.com/defold/examples/tree/master/gui/pointer_over) The "gui" game object contains a GUI component stored in the file *pointer_over.gui*. The GUI contains the setup with the "button" box node for the button image and the "text" text node for the button label text. *pointer_over.gui* has a script attached to it, called *pointer_over.gui_script*, which contains the button logic. ## Scripts ### pointer_over.gui_script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> self.button = gui.get_node("button") -- <2> self.text = gui.get_node("text") -- <3> self.is_over = false -- <4> end function on_input(self, action_id, action) if action_id == nil then --<5> if gui.pick_node(self.button, action.x, action.y) then -- <6> if not self.is_over then gui.set_text(self.text, "HELLO!") -- <7> self.is_over = true end else if self.is_over then gui.set_text(self.text, "BUTTON") -- <8> self.is_over = false end end end end --[[ 1. Tell the engine that this game object wants to receive input. 2. Get the instance for the node named "button" (the button box). 3. Get the instance for the node named "text" (the button label). 4. Trigger for locking multiple execution. 5. If action_id equal nil (pointer is moving) 6. Check if the pointer position (`action.x` and `action.y`) is within the boundaries of the button node. 7. Change the label text in pointer over case. 8. Change the label text to default value. --]] ``` # Slice-9 {#examples:gui:slice9} This example demonstrates slice-9 scaling gui box node. [Project files](https://github.com/defold/examples/tree/master/gui/slice9) Overview : Using a small stylized image (90x91 pixels) we apply it to a gui node and set the slice-9 properties, we can then adjust the size and retain the styling without streching and distortion. [:More on Slice-9 with Defold:](https://defold.com/manuals/gui-box/#slice-9-texturing) The setup consists of a gui collection, gui script, a box node and a texture atlas Box Node : contains: - A texture set to stylized wood plank image. - Size Mode set to Manual - Slice 9 adjusted settings Gui script : Use: - For animating the node to different sizes, showing slice-9 at its potential. ## Scripts ### slice9.gui_script ```lua local shape1 = vmath.vector3(660,576,0) -- < 1 > local shape2 = vmath.vector3(150,500,0) local shape3 = vmath.vector3(350,250,0) local function getshape(self) -- < 2 > local node = gui.get_node("slice_box") local function animate_size(node, shape) -- < 3 > gui.animate(node, "size", shape, gui.EASING_INOUTCUBIC, 1.75, 2.5, getshape, gui.PLAYBACK_ONCE_FORWARD) end if self.shape_number == 1 then animate_size(node, shape1) self.shape_number = 2 elseif self.shape_number == 2 then animate_size(node, shape2) self.shape_number = 3 else animate_size(node, shape3) self.shape_number = 1 end end function init(self) -- < 4 > self.shape_number = 1 getshape(self) end --[[ 1.-Here we create 3 local vector3's representing 3 different sizes for use when animating the gui node size property. 2.-getshape() function gets our slice-9 gui node then an if statement is used to check the shape_number variable and animate_size is set accordingly and shape_number is changed for the next shape. 3.-The function animate_size() takes in the node and shape vector3 and uses them with gui.animate. Here we animate the "size" of the node and after the animation is complete getshape function is called again and a different shape "size" will be animated once again. 4.-In the initialize function we set self.shape_number to 1 and call getshape function to start the looping chained animation. --]] ``` # Stencil {#examples:gui:stencil} A GUI box node with "Clipping mode" set to "STENCIL". This makes it mask its child node (which is called "bunny"). [Project files](https://github.com/defold/examples/tree/master/gui/stencil) ## Scripts ### stencil.gui_script ```lua function init(self) local bunny = gui.get_node("bunny") gui.animate(bunny, "position.x", 150, gui.EASING_INOUTSINE, 3, 0, null, gui.PLAYBACK_LOOP_PINGPONG) end ``` # 8 ways movement {#examples:input:move} A very simple 8 ways movement setup with a single game object and a script that listens to input and updates the game object position accordingly. [Project files](https://github.com/defold/examples/tree/master/input/move) ## Scripts ### move.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> self.vel = vmath.vector3() -- <2> end function update(self, dt) local pos = go.get_position() -- <3> pos = pos + self.vel * dt -- <4> go.set_position(pos) -- <5> self.vel.x = 0 -- <6> self.vel.y = 0 end function on_input(self, action_id, action) if action_id == hash("up") then self.vel.y = 150 -- <7> elseif action_id == hash("down") then self.vel.y = -150 elseif action_id == hash("left") then self.vel.x = -150 -- <8> elseif action_id == hash("right") then self.vel.x = 150 end end --[[ 1. Tell the engine that the current game object ("." is shorthand for that) should receive user input to the function `on_input()` in its script components. 2. Construct a vector to indicate velocity. It will initially be zero. 3. Each frame, get the current position and store in `pos`. 4. Add the velocity, scaled to the current frame length. Velocity is therefore expressed in pixels per second. 5. Set the game object's position to the newly calculated position. 6. Zero out the velocity. If no input is given, there should be no movement. 7. If the user presses "up", set the y component of the velocity to 150. If the user presses "down", set the y component to -150. 8. Similarly, if the user presses "left", set the x component of the velocity to -150. And finally, if the user presses "right", set the x component to 150. --]] ``` # Down duration {#examples:input:down_duration} Listens to input trigger "touch" and count mouse down duration in update method. [Project files](https://github.com/defold/examples/tree/master/input/down_duration) ## Scripts ### down_duration.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> self.message = "Duration: %f . Last duration: %f" -- <2> self.duration = 0 self.last_duration = 0 end local function update_text(self) -- <3> local msg = string.format(self.message, self.duration, self.last_duration) -- <4> label.set_text("#label", msg) -- <5> end function on_input(self, action_id, action) if action_id == hash("touch") then -- <6> if action.pressed then -- <7> self.is_start_timer = true -- <8> elseif action.released then -- <9> self.is_start_timer = false -- <10> self.last_duration = self.duration -- <11> self.duration = 0 update_text(self) -- <12> end end end function update(self, dt) if self.is_start_timer then -- <13> self.duration = self.duration + dt -- <14> update_text(self) -- <15> end end --[[ 1. Tell the engine that this object ("." is shorthand for the current game object) wants to receive input. The function `on_input()` will be called whenever input is received. 2. Prepare format of output including two float placeholders. 3. Create method for updating the text label. 4. Create a formatted string from the format and duration and last_duration arguments. 5. Set the label component to the stored text. 6. Check if we receive an input action named "touch". 7. Check if it is pressed then run the following. 8. Change flag for starting a timer. 9. Check if it is released then run the following. 10. Change flag for stopping a timer. 11. Save duration as last_duration. 12. Run method for updating text. 13. Check if timer is started. 14. Add dt (delta time from the last frame) to the duration variable. 15. Run method for updating text. --]] ``` # Entity Picking {#examples:input:entity_picking} This example demonstrates how to pick a game object from the 3D scene. [Project files](https://github.com/defold/examples/tree/master/input/entity_picking) This example describes method of selecting a game object from the 3D scene on the click of the mouse using collision-based picking: * We use [collision object components](https://defold.com/manuals/physics-objects/) to define a pickable shape for each relevant game object. This example uses 3D physics, which is enabled in the `game.project` file. * When the user clicks the mouse button, we convert screen coordinates to world coordinates and fire a raycast into the 3D world using the `physics.raycast()` function. * If the ray intersects with a collision object, the corresponding game object is considered "picked". The models used in this example are from Kenney's [Prototype Kit](https://kenney.nl/assets/prototype-kit), licensed under CC0. ## Scripts ### entity_picking.script ```lua go.property("camera_url", msg.url("/camera#camera")) --- Performs a raycast from the camera through a screen position to find an entity. -- @param camera_url url The camera URL to use for screen-to-world conversion -- @param screen_x number The x-coordinate on the screen -- @param screen_y number The y-coordinate on the screen -- @param collision_groups table The collision groups to check against as array of hash values -- @return table|nil The first entity hit by the ray, or nil if nothing was hit local function pick_entity(camera_url, screen_x, screen_y, collision_groups) local from = camera.screen_to_world(vmath.vector3(screen_x, screen_y, 0), camera_url) local to = camera.screen_to_world(vmath.vector3(screen_x, screen_y, 100), camera_url) local results = physics.raycast(from, to, collision_groups, { all = false }) if not results then return nil end return results[1] end function init(self) -- Use the projection provided by the camera msg.post("@render:", "use_camera_projection") -- Acquire input focus to receive input events msg.post(".", "acquire_input_focus") self.input_pressed = false -- Tracks if the input is currently pressed self.last_input = nil -- Stores the last input action received self.previous = nil -- Keeps track of the previously highlighted entity end function update(self, dt) if not self.last_input then -- No input received yet return end local result = pick_entity(self.camera_url, self.last_input.screen_x, self.last_input.screen_y, { hash("target") }) if result then -- Store in the result table the model URL of the entity just for convenience result.model_url = msg.url(nil, result.id, "model") -- Set the tint of the entity to highlight it go.set(result.model_url, "tint.w", 1.5) -- If the input is currently pressed, move the camera to the entity if self.input_pressed then -- We want to move the camera to only the X,Y of the entity, so we get its position local move_to = go.get("/camera", "position") move_to.x = result.position.x move_to.y = result.position.y go.cancel_animations("/camera", "position") go.animate("/camera", "position", go.PLAYBACK_ONCE_FORWARD, move_to, go.EASING_INOUTQUAD, 0.5) end -- If the previously highlighted entity is different from the current entity, reset its tint if self.previous and self.previous.id ~= result.id then go.set(self.previous.model_url, "tint.w", 1) end self.previous = result else -- No entity was hit, so reset the tint of the previously highlighted entity if self.previous then go.set(self.previous.model_url, "tint.w", 1) self.previous = nil end end end function on_input(self, action_id, action) if action_id == hash("touch") then -- "touch" is a screen touch or mouse click. We only want to react to the press event. self.input_pressed = action.pressed elseif not action_id then -- If action_id is nil, it means that the action is a mouse move event. -- "action" contains the mouse move event data. We want to store it for later use. self.last_input = action end end ``` # Mouse and touch events {#examples:input:mouse_and_touch} Shows how to read mouse/touch movement and mouse/touch button state. [Project files](https://github.com/defold/examples/tree/master/input/mouse_and_touch) ## Scripts ### mouse_and_touch.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> self.state = "-" end function on_input(self, action_id, action) local pos = vmath.vector3(action.x, action.y, 0) -- <2> if action_id == hash("touch") then -- <3> if action.pressed then -- <4> self.state = "pressed" elseif action.released then -- <5> self.state = "-" end end local text = ("x: %d y: %d state: %s"):format(pos.x, pos.y, self.state) label.set_text("#label", text) end --[[ 1. Tell the engine that this object ("." is shorthand for the current game object) wants to receive input. The function `on_input()` will be called whenever input is received. 2. Read the position of the mouse pointer or touch event 3. The left mouse button in the input bindings will also be used for touch events on a phone/tablet 4. The 'pressed' state will be true on the frame when the mouse button/finger is pressed 5. The 'released' state will be true on the frame when the mouse button/finger is released --]] ``` # Text input {#examples:input:text} Listens to text input trigger "type" and modifies the game object label with the alien's speech according to input. A "backspace" key trigger has also been added. [Project files](https://github.com/defold/examples/tree/master/input/text) ## Scripts ### text.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> self.message = "" -- <2> end function on_input(self, action_id, action) if action_id == hash("type") then self.message = self.message .. action.text -- <3> label.set_text("#label", self.message) -- <4> elseif action_id == hash("backspace") and action.repeated then local l = string.len(self.message) self.message = string.sub(self.message, 0, l-1) -- <5> label.set_text("#label", self.message) -- <6> end end --[[ 1. Tell the engine that this object ("." is shorthand for the current game object) wants to receive input. The function `on_input()` will be called whenever input is received. 2. Store a variable in the script component with the text that the user types. 3. If the "type" text trigger action is sent, add the typed text to the variable `message` that stores the text. 4. Set the label component to the stored text. 5. If the user presses backspace, set the stored text to a substring starting at the beginning of the stored text and ending at the length of the stored text minus 1. This erases the last character from the stored text. 6. Set the label component to the stored text. --]] ``` # Billboarding {#examples:material:billboarding} This example shows how to make sprites and particle sprites face the camera using a custom vertex shader. [Project files](https://github.com/defold/examples/tree/master/material/billboarding) This example shows how to render **camera-facing quads (billboards)** in 3D using Defold materials. The core idea is to keep using Defold's built-in sprite/particle fragment shader, but replace the vertex shader so that each quad is re-oriented towards the camera. The effect is used in two places: - **Sprite components** for trees and rocks - **ParticleFX emitters** for smoke ## Material setup Create a custom material for billboarding (for example `example/billboard.material`) and set it up like this: - **Vertex program:** `example/billboard.vp` - **Fragment program:** `/builtins/materials/particlefx.fp` - This keeps standard particle/sprite sampling, tinting and alpha handling. The material must provide these shader inputs: - **Vertex attributes** | Name | Semantic Type | Vector Type | Description | |-----------------|----------------|-------------|----------------------------------------------------------------| | `position` | Position | Vector | Local quad vertex position | | `mtx_world` | World matrix | Mat4 | Quad center (translation) and scale; coordinate space: World | | `color` | Color | Vector | Forwarded to the fragment shader (for particlefx) | | `billboard_mode`| None | Scalar | Selects the billboarding mode per instance/emitter | - **Vertex constants** | Name | Type | Description | |-------------|------------|--------------------------------------------------| | `view_proj` | `ViewProj` | Transforms world position to clip space | | `view` | `View` | Used to derive camera right/up vectors in world | ## Sprite setup (foliage/rocks) The foliage and rock game objects (for example `assets/foliage/tree1.go` and `assets/foliage/rock1.go`) each contain: 1. A **Sprite** component using the atlas `assets/foliage/foliage.atlas` 2. The material `example/billboard.material` 3. A per-sprite vertex attribute: - `billboard_mode = 1.0` (axis-locked billboard; see below) This is enough to make each sprite face the camera without changing the sprite's transform in the game logic. ## ParticleFX setup (smoke) The smoke effect is defined in `assets/smoke/smoke.particlefx`. The relevant settings are: 1. **Emitter material:** `example/billboard.material` 2. **Emitter attribute:** `billboard_mode = 0.0` (screen-aligned billboard; see below) 3. **Emission space:** `World` - This ensures particles exist in world space, while still being oriented towards the camera by the vertex shader. ## Billboard modes The vertex shader supports two simple modes controlled by `billboard_mode`: - `0.0` - **screen-aligned** billboard (faces the camera fully using the camera's right/up vectors) - `1.0` - **axis-locked** billboard (rotates only around the world Y axis; useful for upright foliage) You can set this value per Sprite instance or per ParticleFX emitter. ## Camera This example uses the [Simple FPS Camera extension by Jhonny](https://github.com/Jhonnyg/defold-vantage) for camera control: - Click Left Mouse Button and move to orbit the camera around the scene. - Scroll to zoom in or out. ## Credits Assets by: - 3D buildings and props by Kay Lousberg: [KayKit - Medieval Hexagon](https://kaylousberg.itch.io/kaykit-medieval-hexagon) - Trees and rocks - screenshots of 3D models by Kenney: [Fantasy Town Kit](https://kenney.nl/assets/fantasy-town-kit) - Particlefx smoke texture - Defold Foundation - free to use - CC0 ## Scripts ### billboard.vp ```glsl #version 140 in highp vec4 position; // Local quad vertex position (XY plane). in highp mat4 mtx_world; // Per-instance world matrix (translation = center, columns contain scale). in mediump vec2 texcoord0; in mediump vec4 color; in lowp float billboard_mode; // 0.0 = screen-aligned, 1.0 = axis-locked (world Y axis). uniform vs_uniforms { mat4 view_proj; // View matrix used to derive camera basis vectors (right/up) and camera position. mat4 view; mat4 proj; }; out mediump vec2 var_texcoord0; out mediump vec4 var_color; // Screen-aligned billboard: // Uses camera right/up vectors (from the view matrix) so the quad always faces the camera. vec3 computeScreenBillboard(vec3 center, vec2 local, float scaleX, float scaleY) { // Camera basis vectors in world space. vec3 right = vec3(view[0][0], view[1][0], view[2][0]); vec3 up = vec3(view[0][1], view[1][1], view[2][1]); return center + right * local.x * scaleX + up * local.y * scaleY; } // Axis-locked billboard (Y-up): // Rotates towards the camera only around the world Y axis, keeping the quad upright. vec3 computeAxisLockedBillboard(vec3 center, vec2 local, float scaleX, float scaleY) { vec3 world_up = vec3(0.0, 1.0, 0.0); // Reconstruct camera world position from the view matrix. // (Equivalent to inverse(view) * vec4(0,0,0,1), but cheaper.) vec3 camera_position = vec3( -dot(view[0].xyz, view[3].xyz), -dot(view[1].xyz, view[3].xyz), -dot(view[2].xyz, view[3].xyz) ); vec3 camera_vector = camera_position - center; // Project onto horizontal plane so we only rotate around Y. camera_vector.y = 0.0; // Avoid NaN when the camera is directly above the center (zero-length vector). if (length(camera_vector) < 0.0001) { camera_vector = vec3(0.0, 0.0, 1.0); } camera_vector = normalize(camera_vector); vec3 right = normalize(cross(world_up, camera_vector)); vec3 up = world_up; return center + right * local.x * scaleX + up * local.y * scaleY; } void main() { // Extract per-instance scale from the world matrix columns. // This preserves scaling applied to the sprite/particle in the editor. float scaleX = length(mtx_world[0].xyz); float scaleY = length(mtx_world[1].xyz); // Billboard center in world space is the translation part of the world matrix. vec3 center_position = mtx_world[3].xyz; // Local quad coordinates (in the same space as sprite/particle vertex data). vec2 local_position = position.xy; vec3 world_position; // Select the billboarding mode (treat anything < 1.0 as mode 0). if (billboard_mode < 1.0) { world_position = computeScreenBillboard(center_position, local_position, scaleX, scaleY); } else { world_position = computeAxisLockedBillboard(center_position, local_position, scaleX, scaleY); } // Transform to clip space and forward varyings to the fragment stage. gl_Position = view_proj * vec4(world_position, 1.0); var_texcoord0 = texcoord0; // Premultiply RGB by alpha to match Defold's built-in particle/sprite expectations. var_color = vec4(color.rgb * color.a, color.a); } ``` # Custom Sprite {#examples:material:custom_sprite} This example demonstrates a simple way to create and apply a custom sprite shader for changing colors and customizing an outline. [Project files](https://github.com/defold/examples/tree/master/material/custom_sprite) If your game requires a sprite that can be recolored and reused, a custom shader will be needed. Your sprite's artwork can be composed in such a way that will help achieve things you may want to do. For example an outline around your sprite that can be turned off/on and color changed. When creating your artwork if your sprite's green-channel is shifted slightly below 1.0 and you add an outline around your sprite with full green color equal to 1.0 then in the shader you can manage the green channel values that match 1.0 and change the color or completely hide these values thus removing the outline altogether. Recoloring sprites to be used throughout a game is pretty common. One way to achieve re-coloring with a range of values instead of a single color is to de-saturate a part of the sprite you want to recolor. When you de-saturate an image it will even out the red, green and blue channel values to a grey-scale. You can then check in the shader for these grey-scale values and change the colors. To check for these values you can add 2 or 3 channels together as a float value and then with another float multiply a single channel by 2 or 3, we then compare these values when valid use a new color. In the example the custom sprite material has 2 vertex attributes each is a vector 4 of float values. The values are used for coloring the fluid and the outline from a script to the shader. The script has a function for creating a random color and also sets the color vertex properties ## Scripts ### set_color.script ```lua local sprite_to_color = "/new#sprite" local brightness = 0.3 local function random_color(self) -- create a new_color of random-ish float values (0.3 or 1.3) local random_number_r = math.random(0, 1)+brightness local random_number_b = math.random(0, 1)+brightness local random_number_g = math.random(0, 1)+brightness local new_color = vmath.vector4(random_number_r, random_number_g, random_number_b, self.outline_io) return new_color end function init(self) msg.post("@render:", "clear_color", { color = vmath.vector4(0.25960784,0.2315686274509804,0.229607843, 1.0) } ) self.outline_io = 0.0 -- float is used when setting the w value of the material vertex attribute "outline" 0.0 = off 1.0 = on math.randomseed(socket.gettime()*10000) end function on_message(self, message_id, message) if message_id == hash("outline_io") then if self.outline_io <= 0.0 then self.outline_io = 1.0 else self.outline_io = 0.0 end go.set(sprite_to_color, "outline.w", self.outline_io) elseif message_id == hash("outline_color") then go.set(sprite_to_color, "outline", random_color(self)) -- set color for outline elseif message_id == hash("fluid_color") then go.set(sprite_to_color, "newcolor", random_color(self)) -- set color for potion fluid end end ``` ### recolor.fp ```glsl #version 140 uniform sampler2D texture_sampler; uniform f_uniform { vec4 tint; }; in vec2 var_texcoord0; // custom vertex attributes in vec4 new_color; in vec4 new_outline; out vec4 final_color; void main() { lowp vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w); lowp vec4 sprite = texture(texture_sampler, var_texcoord0.xy); // float values used for comparing lowp float combine = (sprite.r + sprite.g); lowp float greenmul = sprite.g * 2; // when 2 channels added together equal the same as a single channel multipled then we have desaturated values if(combine == greenmul){ sprite = vec4(sprite.rgb*new_color.rgb,sprite.a); } // when the green channel has a value of 1.0 and the w value is 1.0(on) then we color the outline if(new_outline.w >= 1.0 && sprite.g >= 1.0){ sprite = vec4(new_outline.rgb,1.0); } else if (sprite.g >= 1.0){ //when the w value is not 1.0 we remove all values. turning the outline off sprite = vec4(0.0, 0.0, 0.0, 0.0); } final_color = vec4(sprite * tint); } ``` ### recolor.vp ```glsl #version 140 uniform v_inputs { mat4 view_proj; }; // positions are in world space in vec4 position; in vec2 texcoord0; // custom vertex attributes from material in vec4 newcolor; in vec4 outline; out vec2 var_texcoord0; // custom vertex attributes sent to fragment program out vec4 new_color; out vec4 new_outline; void main() { gl_Position = view_proj * vec4(position.xyz, 1.0); var_texcoord0 = texcoord0; new_color = newcolor; new_outline = outline; } ``` # Noise shader {#examples:material:noise} This example shows how to use a noise function to generate clouds, smoke or similar effect using a shader. [Project files](https://github.com/defold/examples/tree/master/material/noise) This example contains a game object with a model component. The model component uses the `/builtins/assets/meshes/quad.dae` mesh, which is a rectangle 1 by 1 unit large. The game object is scaled to the dimensions of the screen so that the mesh covers the entire screen. The shader applies multiple layers of noise to the uv coordinate to create a two dimensional flowing cloud or smoke like look. The shader also receives a time value from `noise.script` and applies this in the calculation to apply movement to the visual effect. ## Scripts ### noise.script ```lua function init(self) self.time = 0 end function update(self, dt) self.time = self.time + dt -- set the x component of the 'time' fragment constant in the material go.set("#model", "time.x", self.time) end ``` ### noise.fp ```glsl #version 140 in mediump vec2 var_texcoord0; uniform fs_uniforms { mediump vec4 time; }; out mediump vec4 out_fragColor; // noise shader from https://www.shadertoy.com/view/XXBcDz // pseudo random generator (white noise) float rand(vec2 n) { return fract(sin(dot(n, vec2(12.9898, 78.233))) * 43758.5453); } // value noise float noise(vec2 p) { vec2 ip = floor(p); vec2 u = fract(p); u = u * u * (3.0 - 2.0 * u); float x = mix(rand(ip), rand(ip + vec2(1.0, 0.0)), u.x); float y = mix(rand(ip + vec2(0.0, 1.0)), rand(ip + vec2(1.0, 1.0)), u.x); float a = u.y; float res = mix(x, y, a); return res * res; } // used to rotate domain of noise function const mat2 rot = mat2( 0.80, 0.60, -0.60, 0.80 ); // fast implementation float fbm( vec2 p ) { float f = 0.0; f += 0.500000 * noise( p ); p = rot * p * 2.02; f += 0.031250 * noise( p ); p = rot * p * 2.01; f += 0.250000 * noise( p ); p = rot * p * 2.03; f += 0.125000 * noise( p + 0.1 * sin(time.x) + 0.8 * time.x ); p = rot * p * 2.01; f += 0.062500 * noise( p + 0.3 * sin(time.x) ); p = rot * p * 2.04; f += 0.015625 * noise( p ); return f / 0.96875; } void main() { float n = fbm(var_texcoord0.xy); out_fragColor = vec4(n, n, n, 1.0); } ``` # Repeating Background {#examples:material:repeating_background} Create a scrolling background using a repeating texture on a model quad. [Project files](https://github.com/defold/examples/tree/master/material/repeating_background) A repeating, scrolling texture can add visual interest to a static background. This example demonstrates how to create an infinitely tiling background using a model quad with a repeating texture. The effect is achieved by scrolling the UV coordinates over time, creating smooth, continuous motion. The script driving the effect works as follows: * Each frame it reads the current window size and scales the `background` game object so the quad covers the full viewport. The rotation is set via `euler.z` (Rotation Z in the IDE). * It converts the window size into a UV repeat scale (`uv_params.x/y`) so the texture tiles across the screen. * It advances a scrolling offset based on `scroll_speed` and `tile_size`, wraps it to the 0..1 range, and sends `uv_params` to the model material. The asset used in this example is from Kenney's [Puzzle Pack 2](https://www.kenney.nl/assets/puzzle-pack-2), licensed under CC0. ## Scripts ### repeating_background.script ```lua -- Size of a single tile in pixels go.property("tile_size", 128) -- Scroll speed vector (x, y, z) in pixels per second go.property("scroll_speed", vmath.vector3(50, 0, 0)) -- Applies layout based on current window size -- Scales the game object to fill the entire window and calculates UV scale local function apply_layout(self) local width, height = window.get_size() -- Scale the game object to match window dimensions go.set(".", "scale", vmath.vector3(width, height, 1)) -- Calculate how many tiles fit in the window (for UV tiling) self.uv_scale = vmath.vector3(width / self.tile_size, height / self.tile_size, 0) -- Send UV parameters to the shader: scale (x, y) and offset (z, w) local uv_params = vmath.vector4(self.uv_scale.x, self.uv_scale.y, self.offset.x, self.offset.y) go.set("#model", "uv_params", uv_params) end -- Updates UV offset for scrolling animation -- Moves the texture offset based on scroll speed and wraps it using modulo local function update_uv_params(self, dt) -- Calculate offset delta in tile units (0-1 range) local delta = self.scroll_speed * dt / self.tile_size -- Update offset (subtract because we want to scroll in the direction of scroll_speed) self.offset = self.offset - delta -- Wrap offset to 0-1 range to create seamless repeating self.offset.x = self.offset.x % 1 self.offset.y = self.offset.y % 1 -- Send updated UV parameters to the shader local uv_params = vmath.vector4(self.uv_scale.x, self.uv_scale.y, self.offset.x, self.offset.y) go.set("#model", "uv_params", uv_params) end -- Initialize the script -- Sets up the initial UV offset to zero function init(self) self.offset = vmath.vector3(0) end function final(self) end -- Update function called every frame -- Applies layout and updates UV parameters for scrolling function update(self, dt) apply_layout(self) update_uv_params(self, dt) end ``` ### repeating_background.vp ```glsl #version 140 in vec4 position; in vec2 texcoord0; uniform vp_uniforms { mat4 mtx_worldview; mat4 mtx_proj; vec4 uv_params; }; out vec2 var_texcoord0; void main() { // uv_params.x = repeat scale on U axis (tiles across width) // uv_params.y = repeat scale on V axis (tiles across height) // uv_params.z = scroll offset on U axis (normalized 0..1) // uv_params.w = scroll offset on V axis (normalized 0..1) var_texcoord0 = texcoord0 * uv_params.xy + uv_params.zw; gl_Position = mtx_proj * mtx_worldview * vec4(position.xyz, 1.0); } ``` ### repeating_background.fp ```glsl #version 140 in mediump vec2 var_texcoord0; out vec4 out_fragColor; uniform mediump sampler2D texture0; void main() { out_fragColor = texture(texture0, var_texcoord0); } ``` # Screenspace {#examples:material:screenspace} This example shows how to create a custom material with two textures that blend together to create a pattern effect using screen space coordinates. [Project files](https://github.com/defold/examples/tree/master/material/screenspace) In this example, we create a new material for 3D models in which we convert vertex coordinates to screenspace to get a special effect. It may be called "surface fill", "screenspace fill" and is used, most often in combination with outlines, to highlight objects in 3D games or indicate their status. We added two game objects and two models to which we assigned our new `screenspace` material. The material is based on [`unlit`](/examples/material_unlit/), but in it: - vertex shader: we added a conversion of the clip space position to the screen position to pass that value to the fragment shader. - fragment shader: we added sampling the color based on screenspace coordinates and blending into the final output color. - material properties: we added a new sampler to set a second texture to be used as a pattern, and user-defined uniforms to control the fragment shader. The last important thing is to pass the screen size to the shader to adjust the aspect ratio: ```lua local w, h = window.get_size() go.set("#model", "screen_size", vmath.vector4(w, h, 0, 0)) ``` The shaders are written in GLSL 1.40, which is available from Defold 1.9.2. The model used in this example is from Kenney's [Prototype Pack](https://kenney.nl/assets/prototype-kit), licensed under CC0. ## Scripts ### screenspace.script ```lua function init(self) self.time = 0 -- for pattern animation -- The model with the pattern - we enabled the effect, 0.5 is the intensity (alpha) go.set("/crate_selected#model", "pattern_opts.x", 0.5) -- + add 70 degrees to the rotation go.set("/crate_selected#model", "pattern_opts.w", math.rad(70)) -- The normal model - the 0.0 value disables the effect go.set("/crate#model", "pattern_opts.x", 0) end function update(self, dt) -- Animate the pattern by changing the z value self.time = self.time - dt go.set("/crate_selected#model", "pattern_opts.z", self.time) -- The shader uses the screen size to calculate the aspect ratio. -- In a real game, you'd set this in the render script globally for all materials. local w, h = window.get_size() go.set("/crate_selected#model", "screen_size", vmath.vector4(w, h, 0, 0)) end ``` ### screenspace.vp ```glsl #version 140 // The model's vertex position and texture coordinates. in vec4 position; in vec2 texcoord0; // The projection, view and world matrices. uniform general_vp { mat4 mtx_world; mat4 mtx_view; mat4 mtx_proj; }; // The output of a vertex shader are passed to the fragment shader. // The texture coordinates of the vertex. out vec2 var_texcoord0; // The screen texture coordinates of the vertex. out vec4 var_screen_texcoord; // Converts the clip space position to the screen position. vec4 clip_to_screen(vec4 pos) { // Position is [-w,w], convert to [-0.5w,0.5w] vec4 o = pos * 0.5; // Convert from [-0.5w + 0.5w,0.5w + 0.5w] to [0,w] o.xy = vec2(o.x, o.y) + o.w; // Keep "zw" as it is o.zw = pos.zw; return o; } void main() { // Pass the texture coordinates to the fragment shader. var_texcoord0 = texcoord0; // Transform the vertex position to clip space. vec4 vertex_pos = mtx_proj * mtx_view * mtx_world * vec4(position.xyz, 1.0); gl_Position = vertex_pos; // Convert the clip space position to the screen position and pass the value to the fragment shader. var_screen_texcoord = clip_to_screen(vertex_pos); } ``` ### screenspace.fp ```glsl #version 140 // Inputs should match the vertex shader's outputs. in vec2 var_texcoord0; in vec4 var_screen_texcoord; // The color texture. uniform lowp sampler2D texture0; // The pattern texture. uniform lowp sampler2D texture_pattern; // The user defined uniforms. uniform user_fp { // pattern_opts.x - alpha, default 1.0 (set 0.0 to disable the screen space effect). // pattern_opts.y - scale, default 30.0. // pattern_opts.z - offset by x, default 0.0. // pattern_opts.w - rotation in radians. vec4 pattern_opts; // The screen size, used to calculate the aspect ratio. vec4 screen_size; }; // The final color of the fragment. out lowp vec4 final_color; // Rotate 2D vector "v" by the "a" angle in radians vec2 rotate(vec2 v, float a) { float s = sin(a); float c = cos(a); return mat2(c, s, -s, c) * v; } void main() { // Sample the color texture at the fragment's texture coordinates. vec4 color = texture(texture0, var_texcoord0.xy); // Counteract the perspective correction and scale the coords. vec2 pattern_coord = (var_screen_texcoord.xy / var_screen_texcoord.w) * pattern_opts.y; // + Correct the aspect ratio float aspect = screen_size.x / screen_size.y; pattern_coord.x *= aspect; // + Offset the grid horizontally pattern_coord.x += pattern_opts.z; // + Rotate pattern_coord = rotate(pattern_coord, pattern_opts.w); // Output the sampled color if (pattern_opts.x > 0.0) { // Sample the pattern at the screen space texture coordinates. vec4 pattern_color = texture(texture_pattern, pattern_coord); // Blend the colors: (sRGBA*1) + (dRGBA*(1-sA)) final_color = pattern_color * pattern_opts.x + color * (1.0 - (pattern_color.a * pattern_opts.x)); } else { // No pattern, just output the color. final_color = color; } } ``` # Sprite local UV {#examples:material:sprite_local_uv} This example shows how to get local UV coordinates of a sprite regardless of sprite size [Project files](https://github.com/defold/examples/tree/master/material/sprite_local_uv) The example uses two game objects, each with a sprite component and a script. The sprite component uses a custom sprite material `sprite_local_uv.material` with `local_position` and `sprite_size` as two vertex attributes. The `local_position` attribute is of semantic type "Position" and coordinate space "Local" while the `sprite_size` attribute is of semantic type "User" and will be set by the script. The script gets the size of the sprite and sets it as the `sprite_size` vertex attribute. ## Scripts ### sprite_local_uv.script ```lua function init(self) -- get the sprite size from the sprite component propertry 'size' local size = go.get("#sprite", "size") -- set the size on the sprite material in the custom vertex attribute 'sprite_size' go.set("#sprite", "sprite_size", size) -- rotate the sprite go.animate(".", "euler.z", go.PLAYBACK_LOOP_FORWARD, 360, go.EASING_LINEAR, 5) end ``` ### sprite_local_uv.vp ```glsl #version 140 // positions are in world space in highp vec4 position; in mediump vec2 texcoord0; // position in local space in highp vec2 position_local; // size of sprite in pixels in mediump vec2 sprite_size; out mediump vec2 var_texcoord0; out highp vec2 var_position_local; uniform vs_uniforms { highp mat4 view_proj; }; void main() { gl_Position = view_proj * vec4(position.xyz, 1.0); var_texcoord0 = texcoord0; // calculate normalized local position and pass it on to the fragment program var_position_local = (position_local + sprite_size * 0.5) / sprite_size; } ``` ### sprite_local_uv.fp ```glsl #version 140 // from sprite_local_uv.vp in mediump vec2 var_texcoord0; in highp vec2 var_position_local; out vec4 out_fragColor; uniform mediump sampler2D texture_sampler; uniform fs_uniforms { mediump vec4 tint; }; void main() { // Pre-multiply alpha since all runtime textures already are mediump vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w); // sample color from sprite texture vec4 color = texture(texture_sampler, var_texcoord0.xy) * tint_pm; // mix local position with red and green color of sprite to // create a gradient across the entire sprite out_fragColor.rg = mix(color.rg, var_position_local.xy, 0.3); // use blue and alpha from the sprite out_fragColor.b = color.b; out_fragColor.a = color.a; } ``` # Sprite Vertex Color Attribute {#examples:material:vertexcolor} This example shows how to set and animate a vertex attribute [Project files](https://github.com/defold/examples/tree/master/material/vertexcolor) The `vertexcolor.script` sets the vertex attribute "mycolor", which has been specified in the material. The shaders specified by the material also makes use of the `mycolor` attribute to colorize the sprites. The vertex attributes can also be animated. Click the image for an animation effect. ## Scripts ### vertexcolor.script ```lua function init(self) msg.post(".", "acquire_input_focus") local scale = 0.75 local spacingx = 160 * scale + 10 local spacingy = 190 * scale + 10 local startx = 40 + spacingx*0.5 local starty = 40 + spacingy*0.5 local maxy = 3 local maxx = 4 self.urls = {} -- 1. For all sprites in the example we set a slightly different `mycolor` vertex attribute: for y = 0, maxy do for x = 0, maxx do local p = vmath.vector3(startx + x*spacingx, starty + y*spacingy, 0.5) local id = factory.create("#factory", p, nil, nil, vmath.vector3(0.8, 0.8, 1)) local url = msg.url(nil, id, "sprite") table.insert(self.urls, url) -- set vertex attribute: go.set(url, "mycolor", vmath.vector4(x/maxx, y/maxy, 0, 1)) end end self.updated = false self.animation_finished = true end function update(self, dt) self.updated = true end function on_input(self, action_id, action) -- 2. On click we animate the `mycolor` vertex attribute of each of the sprites to blue and back. if action_id == hash("touch") and action.pressed and self.updated and self.animation_finished then for _, url in ipairs(self.urls) do self.animation_finished = false -- animate vertex attribute: go.animate(url, "mycolor", go.PLAYBACK_ONCE_PINGPONG, vmath.vector4(0, 0, 1, 1), go.EASING_LINEAR, 1, 0, function() self.animation_finished = true end) end end end ``` ### vertexcolor.vp ```glsl #version 140 // positions are in world space in highp vec4 position; in mediump vec2 texcoord0; in mediump vec4 mycolor; // 1. Add attribute definition out mediump vec2 var_texcoord0; out mediump vec4 var_mycolor; // 2. Add output variable to pass color to fp uniform vs_uniforms { highp mat4 view_proj; }; void main() { gl_Position = view_proj * vec4(position.xyz, 1.0); var_texcoord0 = texcoord0; var_mycolor = mycolor; // 3. Pass mycolor attribute value to fp. } ``` ### vertexcolor.fp ```glsl #version 140 in mediump vec2 var_texcoord0; in mediump vec4 var_mycolor; // 4. Add var_mycolor definition out vec4 out_fragColor; uniform mediump sampler2D texture_sampler; void main() { // Pre-multiply color to match premultiplied textures mediump vec4 tint_pm = vec4(var_mycolor.rgb * var_mycolor.a, var_mycolor.a); out_fragColor = texture(texture_sampler, var_texcoord0.xy) * tint_pm; } ``` # Unlit {#examples:material:unlit} This example demonstrates how to create and apply an custom non-lit material to a 3D model. [Project files](https://github.com/defold/examples/tree/master/material/unlit) In industry-established terms, a material that is not affected by lighting is called "unlit" or "non-lit". It is used to create retro-style graphics or for effects that should not depend on lighting (headlights, lamps). This example contains a game object with a model that has an `unlit` material applied to it. The material is assigned custom vertex and fragment shaders. The shader is very simple and just transfers the texture color to the model. This is an excellent starting point for creating new materials and for creating effects that do not depend on lighting. The shaders are written in GLSL 1.40, which is available from Defold 1.9.2. The model used in this example is from Kenney's [Train Pack](https://kenney.nl/assets/train-kit), licensed under CC0. ## Scripts ### unlit.vp ```glsl #version 140 // The model's vertex position and texture coordinates. in vec4 position; in vec2 texcoord0; // The model's world matrix. in mat4 mtx_world; // The projection and view matrices. uniform general_vp { mat4 mtx_view; mat4 mtx_proj; }; // The output of a vertex shader are passed to the fragment shader. // The texture coordinates of the vertex. out vec2 var_texcoord0; void main() { // Pass the texture coordinates to the fragment shader. var_texcoord0 = texcoord0; // Transform the vertex position to clip space. gl_Position = mtx_proj * mtx_view * mtx_world * vec4(position.xyz, 1.0); } ``` ### unlit.fp ```glsl #version 140 // Inputs should match the vertex shader's outputs. in vec2 var_texcoord0; // The texture to sample. uniform lowp sampler2D texture0; // The final color of the fragment. out lowp vec4 final_color; uniform fs_uniforms { mediump vec4 tint; }; void main() { // Pre-multiply alpha since all runtime textures already are vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w); // Sample the texture at the fragment's texture coordinates. vec4 color = texture(texture0, var_texcoord0.xy) * tint_pm; // Output the sampled color. final_color = color; } ``` # UV Gradient {#examples:material:uvgradient} This example shows how to apply a basic shader to a full screen quad. [Project files](https://github.com/defold/examples/tree/master/material/uvgradient) This example contains a game object with a model component. The model component uses the `/builtins/assets/meshes/quad.dae` mesh, which is a rectangle 1 by 1 unit large. The game object is scaled to the dimensions of the screen so that the mesh covers the entire screen. The shader is very basic and sets the fragment color based on the UV position, thus creating a color gradient. This is a good starting point when experimenting with graphical effects using a shader. ## Scripts ### uvgradient.fp ```glsl varying mediump vec2 var_texcoord0; void main() { gl_FragColor = vec4(var_texcoord0.x, var_texcoord0.y, 0.5, 1.0f); } ``` # Wave Background {#examples:material:wave_background} Shows how to use a Time shader constant to achieve a moving wave effect [Project files](https://github.com/defold/examples/tree/master/material/wave_background) This example contains a game object with a sprite component. The `Image` and `Default Animation properties` of the sprite component cannot be left empty, otherwise an error will occur. In the example the built-in `/builtins/graphics/particle_blob.tilesource` is used and animation is set to `anim`. You can adjust the size of the wave background by modifying the `Size` property of the sprite component. Example uses a Fragment Constant of type `Time` introduced in Defold 1.12.3. ## Scripts ### wave_background.fp ```glsl #version 140 uniform fs_uniforms { vec4 time_data; }; in vec2 var_texcoord0; out vec4 color_out; void main() { // Get the time value automatically passed in by the engine // time_data.x is the total number of seconds since the engine started float t = time_data.x; // 1. Adjust coordinate scaling and tilt // Rotating or offsetting the UV coordinates can create a diagonal effect // We add time to both X and Y to create motion toward the lower-right corner vec2 uv = var_texcoord0 * 8.0; float speed = t * 2.0; // 2. Core wave algorithm // Use sin(x + y - t) to create a wave flowing diagonally // Adding sin(uv.x * 0.5) makes the wave feel distorted instead of like a rigid straight line float wave = sin(uv.x + uv.y - speed + sin(uv.x * 0.8 + speed * 0.5)); // 3. Define the colors vec3 color_bright = vec3(0.0, 0.6, 1.0); // Light blue vec3 color_dark = vec3(0.0, 0.45, 0.9); // Dark blue // 4. Anti-aliased color split // Clamp the smoothing width so the transition stays crisp while still hiding aliasing. float edge_width = clamp(fwidth(wave), 0.01, 0.04); float mask = smoothstep(-edge_width, edge_width, wave); vec3 final_color = mix(color_dark, color_bright, mask); color_out = vec4(final_color, 1.0); } ``` # Mesh {#examples:mesh:triangle} This example shows how to create a basic mesh component in the shape of a triangle. [Project files](https://github.com/defold/examples/tree/master/mesh/triangle) This example contains a game object with a mesh component in the shape of a triangle. The triangle is defined in `triangle.buffer` as the three points of the triangle in the `position` stream. The triangle also defines the colors at each point. The colors get mixed automatically when the triangle is drawn by the shader. ``` [ { "name": "position", "type": "float32", "count": 3, "data": [ -0.5, -0.5, 0, 0.5, -0.5, 0, 0.0, 0.5, 0 ] }, { "name": "color0", "type": "float32", "count": 4, "data": [ 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1 ] } ] ``` ## Scripts ### mesh.fp ```glsl varying mediump vec4 var_color; void main() { gl_FragColor = var_color; } ``` ### mesh.vp ```glsl uniform mediump mat4 mtx_worldview; uniform mediump mat4 mtx_proj; attribute mediump vec4 position; attribute mediump vec4 color0; varying mediump vec4 var_color; void main() { gl_Position = mtx_proj * mtx_worldview * vec4(position.xyz, 1.0); var_color = color0; } ``` # Textured Mesh {#examples:mesh:textured} This example shows how to create a textured mesh component in the shape of a rectangle. [Project files](https://github.com/defold/examples/tree/master/mesh/textured) This example contains a game object with a mesh component in the shape of a rectangle (quad). The quad is defined in `quad.buffer` as the four points (triangle strip) in the `position` stream. The triangle also defines the texture coordinate (UV) at each point. ``` [ { "name": "position", "type": "float32", "count": 3, "data": [ -0.5, -0.5, 0, 0.5, -0.5, 0, -0.5, 0.5, 0, 0.5, 0.5, 0 ] }, { "name": "texcoord0", "type": "float32", "count": 2, "data": [ 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0 ] } ] ``` Texture by [Kenney.nl](https://kenney.nl/assets/prototype-textures) ## Scripts ### texturedmesh.fp ```glsl #version 140 in highp vec4 var_position; in mediump vec2 var_texcoord0; out vec4 out_fragColor; uniform mediump sampler2D tex0; uniform fs_uniforms { mediump vec4 tint; }; void main() { // Pre-multiply alpha since all runtime textures already are vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w); vec4 color = texture(tex0, var_texcoord0) * tint_pm; out_fragColor = vec4(color.rgb, 1.0); } ``` ### texturedmesh.vp ```glsl #version 140 // Positions can be world or local space, since world and normal // matrices are identity for world vertex space materials. // If world vertex space is selected, you can remove the // normal matrix multiplication for optimal performance. in highp vec4 position; in mediump vec2 texcoord0; out highp vec4 var_position; out mediump vec2 var_texcoord0; uniform vs_uniforms { uniform mediump mat4 mtx_worldview; uniform mediump mat4 mtx_proj; uniform mediump mat4 mtx_view; }; void main() { vec4 p = mtx_worldview * vec4(position.xyz, 1.0); var_position = p; var_texcoord0 = texcoord0; gl_Position = mtx_proj * p; } ``` # AABB {#examples:model:aabb} This example demonstrates how to use the `model.get_aabb()` function in a 3D scene. [Project files](https://github.com/defold/examples/tree/master/model/aabb) This example shows how to work with Axis-Aligned Bounding Boxes (AABB) in a 3D scene. The setup consists of falling cubes that are dynamically tracked by a camera using their combined bounding box. The example demonstrates: * How to create and manage a dynamic bounding box that updates with moving objects * Using `model.get_aabb()` to get object bounds * Camera positioning based on bounding box size * Dynamic object spawning with factory * Smooth camera transitions Press SPACE or click to spawn new cubes. The camera will automatically adjust to keep all objects in view based on their combined bounding box. The models used in this example are from Kenney's [Prototype Kit](https://kenney.nl/assets/prototype-kit), licensed under CC0. ## Scripts ### aabb.script ```lua -- -- Dynamic bounding box - it tracks the bounding box of the objects in the scene -- --- Create a new instance -- @return table - the bounding box instance local function bbox_new() return { objects = {}, -- dict for iteration count = 0, min = vmath.vector3(), max = vmath.vector3() } end --- Add an object to the bounding box -- @param bbox table - the bounding box instance -- @param obj_id hash - the object id -- @param aabb table - the aabb of the object local function bbox_add(bbox, obj_id, aabb) if not aabb then aabb = model.get_aabb(msg.url(nil, obj_id, "model")) else assert(types.is_vector3(aabb.min) and types.is_vector3(aabb.max), "AABB is not valid") end local entry = { id = obj_id, position = go.get_position(obj_id), aabb = aabb } bbox.objects[obj_id] = entry bbox.count = bbox.count + 1 end --- Remove an object from the bounding box -- @param bbox table - the bounding box instance -- @param obj_id hash - the object id local function bbox_remove(bbox, obj_id) bbox.objects[obj_id] = nil bbox.count = bbox.count - 1 end --- Update the bounding box -- @param bbox table - the bounding box instance local function bbox_update_all(bbox) bbox.min = vmath.vector3() bbox.max = vmath.vector3() for _, entry in pairs(bbox.objects) do local pos = go.get_position(entry.id) entry.position = pos bbox.min.x = math.min(bbox.min.x, entry.aabb.min.x + pos.x) bbox.min.y = math.min(bbox.min.y, entry.aabb.min.y + pos.y) bbox.min.z = math.min(bbox.min.z, entry.aabb.min.z + pos.z) bbox.max.x = math.max(bbox.max.x, entry.aabb.max.x + pos.x) bbox.max.y = math.max(bbox.max.y, entry.aabb.max.y + pos.y) bbox.max.z = math.max(bbox.max.z, entry.aabb.max.z + pos.z) end end --- Compute the bounding box -- @param bbox table - the bounding box instance -- @return table - result with {center, min, max, radius} local function bbox_compute(bbox) local center = (bbox.min + bbox.max) * 0.5 local radius = vmath.length(bbox.max - bbox.min) * 0.5 return { center = center, min = bbox.min, max = bbox.max, radius = radius } end -- -- Helper functions -- --- Add a cube to the scene -- @param self table - the script instance -- @param x number - the x coordinate -- @param y number - the y coordinate -- @param z number - the z coordinate -- @param color string - the color of the cube - "red" or "white" local function add_cube(self, x, y, z, color) if self.bbox.count >= sys.get_config_int("model.max_count") then print("Increase `model.max_count` and `physics.max_collision_object_count` values!") return end local url = color == "red" and "#factory_box2" or "#factory_box1" local obj_id = factory.create(url, vmath.vector3(x, y, z)) bbox_add(self.bbox, obj_id) go.animate(msg.url(nil, obj_id, "model"), "tint.w", go.PLAYBACK_ONCE_BACKWARD, 3, go.EASING_INQUAD, 0.5) end -- -- Main script -- function init(self) -- Acquire input focus to receive input events msg.post(".", "acquire_input_focus") -- Get the camera default rotation self.camera_euler = go.get("/camera", "euler") -- Create a new dynamic bounding box instance self.bbox = bbox_new() -- Add some cubes to the scene at (0, 1-5, 0) coordinates for i = 1, 10 do local cube_color = i % 2 == 0 and "red" or "white" add_cube(self, (math.random() - 0.5) * 0.1, i / 2, (math.random() - 0.5) * 0.1, cube_color) end bbox_update_all(self.bbox) -- Compute the initial bounding box data self.view = bbox_compute(self.bbox) end function update(self, dt) bbox_update_all(self.bbox) -- Current bounding box data local current = bbox_compute(self.bbox) -- Animate the values for smooth camera movement local t = 0.05 self.view.center = vmath.lerp(t, self.view.center, current.center) self.view.radius = vmath.lerp(t, self.view.radius, current.radius) -- Calculate camera position and rotation local camera_yaw = vmath.quat_rotation_y(math.rad(self.camera_euler.y)) local camera_pitch = vmath.quat_rotation_x(math.rad(self.camera_euler.x)) local camera_rotation = camera_yaw * camera_pitch local camera_zoom = 1.05 * self.view.radius / math.tan(0.5 * go.get("/camera#camera", "fov")) local camera_position = self.view.center + vmath.rotate(camera_rotation, vmath.vector3(0, 0, camera_zoom)) go.set("/camera", "position", camera_position) go.set("/camera", "rotation", camera_rotation) -- Uncomment to benchmark -- add_cube(self, math.random(-3, 3), 10, math.random(-3, 3)) -- add_cube(self, math.random(-3, 3), 10, math.random(-3, 3), "red") end function on_input(self, action_id, action) -- Add a cube to the scene when the mouse button / space key is pressed if (action_id == hash("touch") or action_id == hash("key_space")) and action.pressed then local colors = {"red", "white"} add_cube(self, (math.random() - 0.5) * 0.5, 10, (math.random() - 0.5) * 0.5, colors[math.random(1, 2)]) end end ``` # Character {#examples:model:character} This example shows how to view and play skeletal animations on a glTF model. [Project files](https://github.com/defold/examples/tree/master/model/character) The setup consists of one `player` game object with a `model`, `camera` and `script` component. The `model` component uses "Knight.glb" and "knight_texture.png". The "Knight.glb" file contains meshes and animation data. The `player.script` is used to play different animations from "Knight.glb". The model and assets are [made by Kay Lousberg](https://kaylousberg.com/game-assets/). ## Scripts ### player.script ```lua function init(self) msg.post(".", "acquire_input_focus") model.play_anim("#model", "T-Pose", go.PLAYBACK_LOOP_FORWARD) -- enabled and disable meshes to get the correct look -- weapons model.set_mesh_enabled("#model", "1H_Sword", true) model.set_mesh_enabled("#model", "1H_Sword_Offhand", false) model.set_mesh_enabled("#model", "2H_Sword", false) -- equipment model.set_mesh_enabled("#model", "Knight_Helmet", true) model.set_mesh_enabled("#model", "Knight_Cape", true) -- different shields model.set_mesh_enabled("#model", "Spike_Shield", true) model.set_mesh_enabled("#model", "Round_Shield", false) model.set_mesh_enabled("#model", "Rectangle_Shield", false) model.set_mesh_enabled("#model", "Badge_Shield", false) end function on_input(self, action_id, action) if action_id == hash("key_1") then model.play_anim("#model", "Idle", go.PLAYBACK_LOOP_FORWARD) elseif action_id == hash("key_2") then model.play_anim("#model", "Walking_A", go.PLAYBACK_LOOP_FORWARD) elseif action_id == hash("key_3") then model.play_anim("#model", "1H_Melee_Attack_Chop", go.PLAYBACK_LOOP_FORWARD) elseif action_id == hash("key_4") then model.play_anim("#model", "Block", go.PLAYBACK_LOOP_FORWARD) elseif action_id == hash("key_5") then model.play_anim("#model", "Cheer", go.PLAYBACK_LOOP_FORWARD) end end ``` # Cubemap Reflection {#examples:model:cubemap} This example shows how to use a cubemap to draw environment reflections on a model. [Project files](https://github.com/defold/examples/tree/master/model/cubemap) This example contains a game object with a model component in the shape of the Defold logo. The model has a special `cubemap_model.material` which uses a cubemap sampler to calculate reflections on the model from the cubemap. ## Scripts ### cubemap.script ```lua local ZOOM_SPEED = 0.1 local ROTATION_SPEED = 1 function init(self) msg.post("@render:", "use_camera_projection") msg.post(".", "acquire_input_focus") self.yaw = 0 -- for camera rotation self.pitch = 0 -- for camera rotation self.zoom = 5 -- default zoom self.zoom_offset = 0 -- modification from default zoom end function update(self, dt) local camera_yaw = vmath.quat_rotation_y(math.rad(self.yaw)) local camera_pitch = vmath.quat_rotation_x(math.rad(self.pitch)) local camera_rot = camera_yaw * camera_pitch local camera_position = vmath.rotate(camera_rot, vmath.vector3(0, 0, self.zoom + self.zoom_offset)) go.set_position(camera_position) go.set_rotation(camera_rot) local cameraposv4 = vmath.vector4(camera_position.x, camera_position.y, camera_position.z, 1) go.set("logo#model", "cameraPosition", cameraposv4) end function on_input(self, action_id, action) if action_id == hash("touch") then self.yaw = self.yaw - action.dx * ROTATION_SPEED self.pitch = self.pitch + action.dy * ROTATION_SPEED elseif action_id == hash("mouse_wheel_up") then self.zoom_offset = self.zoom_offset - ZOOM_SPEED elseif action_id == hash("mouse_wheel_down") then self.zoom_offset = self.zoom_offset + ZOOM_SPEED end end ``` ### cubemap_model.fp ```glsl varying mediump vec3 vReflect; uniform samplerCube envMap; void main() { gl_FragColor = textureCube(envMap, vReflect); } ``` ### cubemap_model.vp ```glsl uniform mediump mat4 view_proj; uniform mediump mat4 world; uniform mediump mat4 normal_transform; uniform mediump mat4 world_view; uniform mediump vec4 cameraPosition; attribute mediump vec3 position; attribute mediump vec3 normal; attribute mediump vec2 texcoord0; varying mediump vec3 vReflect; void main() { vec4 worldP = world * vec4(position, 1.0); gl_Position = view_proj * worldP; vec3 worldNormal = normalize(normal); vec3 cameraToVertex = normalize( worldP.xyz - cameraPosition.xyz ); vReflect = reflect( cameraToVertex, worldNormal ); } ``` # GLTF {#examples:model:gltf} This example demonstrates how to use a glTF model. [Project files](https://github.com/defold/examples/tree/master/model/gltf) This example demonstrates how to use glTF models to add a toy car on the scene with a track and animates environment around the car. The models used in this example are from Kenney's [Toy Car Kit](https://kenney.nl/assets/toy-car-kit), licensed under CC0. ## Scripts ### gltf.script ```lua -- This script controls the movement of track parts to create an infinite scrolling effect -- i.e. we don't move the car, we move the track. function init(self) local count = 6 -- Total number of track parts local part_size = 4 -- Size of each track part self.current_z = 0 -- Current z position of the track self.loop_at_z = part_size * (count - 2) -- Point at which to loop the track self.speed = 5 -- Movement speed of the track end function update(self, dt) -- Move the track forward based on speed and delta time self.current_z = self.current_z + self.speed * dt -- Loop the track position when it reaches the loop point if self.current_z > self.loop_at_z then self.current_z = self.current_z - self.loop_at_z end -- Update the position of the track game object go.set("/track", "position.z", self.current_z) end ``` # GPU Skinning {#examples:model:skinning} This example demonstrates GPU skinning. [Project files](https://github.com/defold/examples/tree/master/model/skinning) This example shows how the `model_skinned_instanced.material` is used to render and animate many instances of the same model efficiently using instancing and GPU skinning. Model from the [Universal Animation Library](https://quaternius.itch.io/universal-animation-library). # Model Vertex Color {#examples:model:modelvertexcolor} This example demonstrates how to apply a vertex color shader using exported attributes from a 3D model. [Project files](https://github.com/defold/examples/tree/master/model/modelvertexcolor) Vertex color attributes are usually made up as a vector4 of floats represented as rgba(red, green, blue, alpha) channels. They can be applied to 3d models and exported from many 3d editor applications and are commonly used in games for many effects. This example we are displaying a 3d model with vertex color attribute through a shader. No textures or uv's are used to display the colors. A game object with a model that has a `vertexcolor` material applied to it. The material is assigned custom vertex and fragment shaders. The shader is very simple and just transfers the vertex color data from the model to the vertex and fragment program to display them. The shaders are written in GLSL 1.40, which is available from Defold 1.9.2. ## Scripts ### vertexcolor.vp ```glsl #version 140 // Models vertex color attribute comes in as rgba floats (vec4) in vec4 color; // The model's vertex position. in vec4 position; // The model's world matrix. in mat4 mtx_world; // The projection and view matrices. uniform general_vp { mat4 mtx_view; mat4 mtx_proj; }; // The output of a vertex shader are passed to the fragment shader. out vec4 vertex_color; void main() { // Setting the vertex colors to the passed varying. vertex_color = color; // Transform the vertex position to clip space. gl_Position = mtx_proj * mtx_view * mtx_world * vec4(position.xyz, 1.0); } ``` ### vertexcolor.fp ```glsl #version 140 // Inputs should match the vertex shader's outputs. in vec4 vertex_color; // The final color of the fragment. out lowp vec4 final_color; uniform fs_uniforms { mediump vec4 tint; }; void main() { // brightening up the displayed vertex colors lowp float brightness = 0.1; // Pre-multiply alpha for tint vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w); // Sample the vertex color from vertices, add a little brightness with tint. vec4 color = vertex_color + brightness * tint_pm ; // Output the sampled color. final_color = color; } ``` # Skybox {#examples:model:skybox} This example shows how to create a skybox using a cubemap texture. [Project files](https://github.com/defold/examples/tree/master/model/skybox) This example shows how to create a skybox. A skybox is a technique that makes the scene look bigger and more impressive by wrapping the viewer with a texture that goes around the camera 360 degrees. An in-depth explanation of skybox rendering can be found in [Tutorial 25 of OGL Dev](https://www.ogldev.org/www/tutorial25/tutorial25.html). One of the key components of a skybox is the cubemap texture. A cubemap is a texture that contains 6 individual 2D textures that each form one side of a cube: a textured cube. The cubemap is projected on a sphere or a cube positioned in such a way that the camera and other objects are placed inside the cubemap: Skybox texture by Jockum Skoglund aka hipshot. Free to use. ## Scripts ### skybox.fp ```glsl #version 140 in mediump vec3 var_texcoord0; uniform samplerCube cubemap; void main() { gl_FragColor = texture(cubemap, var_texcoord0); } ``` ### skybox.vp ```glsl #version 140 uniform vs_uniforms { uniform mediump mat4 view_proj; uniform mediump mat4 world; }; in highp vec3 position; out mediump vec3 var_texcoord0; void main() { /* * Transform the position vector using the world view projection matrix * and override the Z component with the W component. After the vertex * shader is complete the rasterizer takes gl_Position vector and performs * perspective divide (division by W) in order to complete the projection. * When we set Z to W we guarantee that the final Z value of the position * will be 1.0. This Z value is always mapped to the far Z. This means that * the skybox will always fail the depth test against the other models in * the scene. That way the skybox will only take up the background left * between the models and everything else will be infront of it. */ mat4 wvp = world * view_proj; vec4 wvp_pos = wvp * vec4(position, 1.0); gl_Position = wvp_pos.xyww; /* * Use the original position in object space as the 3D texture coordinate. * This makes sense because the way sampling from the cubemap works is by * shooting a vector from the origin through a point in the box or sphere. * So the position of the point actually becomes the texture coordinate. * The vertex shader passes the object space coordinate of each vertex as * the texture coordinate and it gets interpolated by the rasterizer for * each pixel. This gives us the position of the pixel which we can use for * sampling. */ var_texcoord0 = position; } ``` # First-person 3D camera and movement {#examples:movement:3d_fps} Control a first-person camera using WASD and mouse to look with cursor lock. [Project files](https://github.com/defold/examples/tree/master/movement/3d_fps) This example shows how to build a simple first-person controller for a 3D scene. You can look around with the mouse and move on the XZ plane using the keyboard (WSAD). ## What you'll learn? - How to implement a FPP camera with mouse to look around. - How to lock/unlock the mouse cursor for immersive camera control. - How to move on a simple XZ plane logic with keyboard input. ## Controls | Input | Action | |------------------------|------------------------------------------------------| | Left mouse click | Lock the cursor and enable mouse look | | Mouse movement | Rotate camera | | `Esc` | Unlock the cursor | | `W`/`S`/`A`/`D` | Move forward/backward/left/right on the ground plane | ## How it works? When the cursor is locked, the script reads mouse movement deltas and rotates the camera accordingly. Movement is normalized to keep a consistent speed in all directions and is clamped within a square area so you cannot wander off the demo scene. Example collection consists of 3 main parts: - `character` - The player character game object includes: - A *script* `character_controller.script` component that implements mouse look, cursor lock/unlock, and WASD movement. - A *camera* component configured with perspective projection. - `scene` - the models used to create a basic 3D environment: - Ground plane scaled to form a walkable area with prototype texture - Walls built from simple cube models with prototype textures - Some decorative trees - `gui` - An on-screen GUI with short instructions. ### Assets Tree models with textures by Kay Louseberg: https://kaylousberg.itch.io/kaykit-forest Prototype textures for Defold by Visionaire: https://github.com/Thevisionaire1/3Deforms ## Script Tuning parameters are defined at the top of `character_controller.script`: - `look_sensitivity` (degrees per pixel) controls how fast the camera rotates - `move_speed` (world units per second) controls walking speed - `move_limit` (half-size in world units) clamps movement within bounds ## Scripts ### character_controller.script ```lua -- First-person 3D camera controller -- Tuning parameters local look_sensitivity = 0.15 -- degrees of camera rotation per 1 pixel of mouse movement local move_speed = 0.5 -- world units per second for camera movement on XZ plane local move_limit = 1.25 -- bounds (half-size) for camera movement on XZ to keep it in a square area function init(self) -- Acquire input focus to receive input events from the engine msg.post(".", "acquire_input_focus") -- Mouse lock state: when true, mouse deltas rotate the camera self.mouse_locked = false -- Initialize yaw/pitch from current rotation (stored in degrees in Defold) self.yaw = go.get(".", "euler.y") self.pitch = go.get(".", "euler.x") -- Input state for continuous movement (WASD) self.input = { forward = false, backward = false, left = false, right = false, } end function update(self, dt) -- Clamp pitch to avoid flipping the camera upside down if self.pitch > 89 then self.pitch = 89 end if self.pitch < -89 then self.pitch = -89 end -- Apply rotation directly via Euler angles (in degrees) go.set(".", "euler", vmath.vector3(self.pitch, self.yaw, 0)) -- Build desired movement direction on XZ plane from input flags local x = (self.input.right and 1 or 0) - (self.input.left and 1 or 0) local z = (self.input.backward and 1 or 0) - (self.input.forward and 1 or 0) -- If there is any movement input, move the camera if x ~= 0 or z ~= 0 then -- Local space direction (camera space) local local_dir = vmath.vector3(x, 0, z) local len = math.sqrt(local_dir.x * local_dir.x + local_dir.z * local_dir.z) if len > 0 then -- Normalize to keep speed consistent diagonally local_dir.x = local_dir.x / len local_dir.z = local_dir.z / len -- Convert the yaw to a quaternion local q_yaw = vmath.quat_rotation_y(math.rad(self.yaw)) -- Convert local movement to world space using current yaw local world_dir = vmath.rotate(q_yaw, local_dir) -- Get the current position of the character local pos = go.get_position() -- Integrate the position pos.x = pos.x + world_dir.x * move_speed * dt pos.z = pos.z + world_dir.z * move_speed * dt -- Clamp the position within the square bounds if pos.x > move_limit then pos.x = move_limit end if pos.x < -move_limit then pos.x = -move_limit end if pos.z > move_limit then pos.z = move_limit end if pos.z < -move_limit then pos.z = -move_limit end -- Set the new position go.set_position(pos) end end end -- Pre-hashed input action ids (must match project input bindings) local KEY_W = hash("key_w") local KEY_S = hash("key_s") local KEY_A = hash("key_a") local KEY_D = hash("key_d") local KEY_ESC = hash("key_esc") local TOUCH = hash("touch") local MOUSE_BUTTON_1 = hash("mouse_button_1") function on_input(self, action_id, action) -- Mouse look when locked: engine provides action.dx/dy even while cursor is locked if self.mouse_locked and (action.dx or action.dy) then -- Rotate the camera based on the mouse movement self.yaw = self.yaw - (action.dx or 0) * look_sensitivity self.pitch = self.pitch + (action.dy or 0) * look_sensitivity end -- Lock on first click (touch or left mouse button) if not self.mouse_locked and action.pressed and (action_id == TOUCH or action_id == MOUSE_BUTTON_1) then -- Lock the mouse window.set_mouse_lock(true) self.mouse_locked = true end -- WSAD - Continuous movement input state (pressed/released) if action_id == KEY_W then -- Set the forward input flag to true if the W key is pressed if action.pressed then self.input.forward = true end if action.released then self.input.forward = false end end if action_id == KEY_S then -- Set the backward input flag to true if the S key is pressed if action.pressed then self.input.backward = true end if action.released then self.input.backward = false end end if action_id == KEY_A then -- Set the left input flag to true if the A key is pressed if action.pressed then self.input.left = true end if action.released then self.input.left = false end end if action_id == KEY_D then -- Set the right input flag to true if the D key is pressed if action.pressed then self.input.right = true end if action.released then self.input.right = false end end -- ESC unlocks the mouse so the cursor is free again if action_id == KEY_ESC and action.pressed then -- Unlock the mouse window.set_mouse_lock(false) self.mouse_locked = false end end ``` # Follow input {#examples:movement:follow} This example shows how to make a game object continuously follow the mouse. [Project files](https://github.com/defold/examples/tree/master/movement/follow) ## Scripts ### follow.script ```lua go.property("speed", 350) -- <1> function init(self) msg.post(".", "acquire_input_focus") -- <2> end function on_input(self, action_id, action) if action_id == hash("touch") or not action_id then -- <3> local current_pos = go.get_position() -- <4> local target_pos = vmath.vector3(action.x, action.y, 0) -- <5> local distance = vmath.length(target_pos - current_pos) -- <6> local duration = distance / self.speed -- <7> go.animate(".", "position", go.PLAYBACK_ONCE_FORWARD, target_pos, go.EASING_LINEAR, duration, 0) -- <8> end end --[[ 1. The speed of the game object in pixels/second 2. Tell the engine that this game object ("." is shorthand for the current game object) should listen to input. Any input will be received in the `on_input()` function. 3. Check if we received mouse movement (no action id) or an input action named "touch" (touch or mouse click) 4. Get the current position of the game object. 5. Set the target position to the position of the mouse or touch. 6. Calculate the distance (length) between the current and target position. 7. Calculate the time it takes to travel the distance given the speed of the game object. 8. Animate the game object's ("." is shorthand for the current game object) position to `target_pos`. --]] ``` # Look at {#examples:movement:look_at} This example shows how to rotate a game object to look at the mouse cursor [Project files](https://github.com/defold/examples/tree/master/movement/look_at) This example shows how to rotate a game object to look at the mouse cursor. It reads the mouse position in `on_input` and uses the mathematical function `math.atan2(x, y)` to calculate the angle between the ray to the point to look at and the positive x-axis. This angle is used to set the rotation of the game object to always look at the mouse position. The example is suitable for the movement in two dimensions, for platformers or top-down games. For 3D objects, check out the [next example](/examples/movement/look_rotation/). ## Scripts ### look_at.script ```lua function init(self) -- make sure the script will receive user input msg.post(".", "acquire_input_focus") end local function look_at(target_position) -- own positon local my_position = go.get_position() -- calculate the angle that this object has to rotate to look at the given point local angle = math.atan2(my_position.x - target_position.x, target_position.y - my_position.y) -- set rotation as a quaternion go.set_rotation(vmath.quat_rotation_z(angle)) end function on_input(self, action_id, action) -- mouse/finger movement has action_id set to nil if not action_id then -- the position to look at (mouse/finger) local target_position = vmath.vector3(action.x, action.y, 0) -- rotate this object to look at the target position look_at(target_position) end end ``` # Look rotation {#examples:movement:look_rotation} This example shows how to rotate a game object to look at the object in 3D space. [Project files](https://github.com/defold/examples/tree/master/movement/look_rotation) This example shows how to orient a game object to look at the target game object in 3D space. For this purpose, we created the function `quat_look_rotation` (also called `LookRotation` or `looking_at` in the industry). This function creates a rotation matrix from the forward and upwards vectors and then converts it to a quaternion. The function also handles the case where no upwards direction is specified, using the default (0, 1, 0) in that case. Note: to properly apply the resulting rotation, you must remember that your game object must face backwards to the "z" axis, i.e. in Defold the "forward" direction is vector (0, 0, -1). In this demo you can rotate the camera by holding down the mouse button. And also switch "targets" by pressing any key. The models used in this example are from Kenney's [Prototype Kit](https://kenney.nl/assets/prototype-kit), licensed under CC0. ## Scripts ### look_rotation.script ```lua --- Creates a rotation with the specified forward and upwards directions. -- @param forward vector3 The forward direction. -- @param upwards vector3|nil The upwards direction. -- @return quat The rotation. local function quat_look_rotation(forward, upwards) -- If no upwards direction is specified, use the default (0, 1, 0) upwards = upwards or vmath.vector3(0, 1, 0) -- No zero vectors if vmath.length_sqr(forward) < 0.0000000001 or vmath.length_sqr(upwards) < 0.0000000001 then return vmath.quat() end -- Create a rotation matrix from the forward and upwards vectors local matrix = vmath.matrix4_look_at(vmath.vector3(0), forward, upwards) -- Convert the matrix to a quaternion and return it return vmath.conj(vmath.quat_matrix4(matrix)) end local function next_target(self) self.target = (self.target or 0) + 1 if self.target > #self.targets then self.target = 1 end local target_id = self.targets[self.target] local from = go.get_position("/sword") local to = go.get_position(target_id) self.target_rotation = quat_look_rotation(to - from) end function init(self) -- Acquire input focus to receive input events msg.post(".", "acquire_input_focus") -- List of target objects self.targets = { "/target1", "/target2", "/target3" } -- Set the initial target next_target(self) end function update(self, dt) -- If a target rotation is set, smoothly rotate the sword to face the target if self.target_rotation then -- Important: we must use vmath.slerp to animate quaternions local q = vmath.slerp(0.15, go.get_rotation("/sword"), self.target_rotation) go.set_rotation(q, "/sword") end end function on_input(self, action_id, action) -- If the left mouse button (or touch) is pressed, set the next target if action_id == hash("mouse_button_left") and action.pressed then next_target(self) end end ``` # Move forward {#examples:movement:move_forward} This example shows how to move a game object in the direction it is rotated/facing. [Project files](https://github.com/defold/examples/tree/master/movement/move_forward) ## Scripts ### move_forward.script ```lua go.property("acceleration", 100) go.property("deceleration", 200) go.property("max_speed", 400) go.property("rotation_speed", 180) -- unit vector pointing up local UP = vmath.vector3(0, 1, 0) function init(self) -- make sure the script will receive user input msg.post(".", "acquire_input_focus") -- movement input self.input = vmath.vector3() -- the current speed (pixels/second) self.speed = 0 end function update(self, dt) -- accelerating? if self.input.y > 0 then -- increase speed self.speed = self.speed + self.acceleration * dt -- cap speed self.speed = math.min(self.speed, self.max_speed) else -- decrease speed when not accelerating self.speed = self.speed - self.deceleration * dt self.speed = math.max(self.speed, 0) end -- apply rotation based on self.input.x (left/right) local rot = go.get_rotation() -- amount to rotate (in radians) local rot_amount = math.rad(self.rotation_speed * self.input.x * dt) -- apply rotation as a quaternion created from a rotation of 'rot_amount' degrees around the z-axis rot = rot * vmath.quat_rotation_z(rot_amount) go.set_rotation(rot) -- move the game object local p = go.get_position() -- amount to move (pixels) local move_amount = UP * self.speed * dt -- apply rotation to movement vector to move game object in the direction of rotation p = p + vmath.rotate(rot, move_amount) go.set_position(p) -- reset input self.input = vmath.vector3() end function on_input(self, action_id, action) -- update direction of movement based on currently pressed keys if action_id == hash("key_up") then self.input.y = 1 elseif action_id == hash("key_down") then self.input.y = -1 elseif action_id == hash("key_left") then self.input.x = 1 elseif action_id == hash("key_right") then self.input.x = -1 end end ``` # Move to target {#examples:movement:move_to} This example shows how to make a game object move to the position the user clicks. [Project files](https://github.com/defold/examples/tree/master/movement/move_to) ## Scripts ### move_to.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> self.moving = false -- <2> end local function moved_to_position(self) -- <9> self.moving = false end function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed then -- <3> if not self.moving then -- <4> msg.post("#label", "disable") -- <5> self.moving = true -- <6> local pos = vmath.vector3(action.x, action.y, 0) -- <7> go.animate(".", "position", go.PLAYBACK_ONCE_FORWARD, pos, go.EASING_LINEAR, 0.5, 0, moved_to_position) -- <8> end end end --[[ 1. Tell the engine that this game object ("." is shorthand for the current game object) should listen to input. Any input will be received in the `on_input()` function. 2. Store a flag in `self` (the current script component) to indicate if the game object is moving or not. 3. If we receive an input action named "touch" and it is pressed then run the following. 4. If the `moving` flag is not set. 5. Disable (don't show) the help text label. 6. Set the `moving` flag. 7. Create a new position called `pos` (of type `vector3`) where the user clicked. 8. Animate the game object's ("." is shorthand for the current game object) position to `pos`. When the animation is done, call the function `moved_to_position()`. 9. The function `moved_to_position()` is called when the animation is done. It just resets the `moving` flag so subsequent clicks will result in a new movement. --]] ``` # Movement speed {#examples:movement:movement_speed} This example shows how to move a game object with accelerating speed. [Project files](https://github.com/defold/examples/tree/master/movement/movement_speed) ## Scripts ### movement_speed.script ```lua go.property("acceleration", 100) go.property("deceleration", 200) go.property("max_speed", 400) function init(self) -- make sure the script will receive user input msg.post(".", "acquire_input_focus") -- movement input self.input = vmath.vector3() -- the current direction of movement self.direction = vmath.vector3() -- the current speed (pixels/second) self.speed = 0 end function update(self, dt) -- is any key pressed? if self.input.x ~= 0 or self.input.y ~= 0 then -- set direction of travel from input self.direction = self.input -- increase speed self.speed = self.speed + self.acceleration * dt -- cap speed self.speed = math.min(self.speed, self.max_speed) else -- decrease speed when no key is pressed self.speed = self.speed - self.deceleration * dt self.speed = math.max(self.speed, 0) end -- move the game object local p = go.get_position() p = p + self.direction * self.speed * dt go.set_position(p) -- reset input self.input = vmath.vector3() end function on_input(self, action_id, action) -- update direction of movement based on currently pressed keys if action_id == hash("key_up") then self.input.y = 1 elseif action_id == hash("key_down") then self.input.y = -1 elseif action_id == hash("key_left") then self.input.x = -1 elseif action_id == hash("key_right") then self.input.x = 1 end end ``` # Moving game object {#examples:movement:simple_move} This example shows how to move a game object. [Project files](https://github.com/defold/examples/tree/master/movement/simple_move) ## Scripts ### simple_move.script ```lua function init(self) self.center = vmath.vector3(360, 360, 0) -- <1> self.radius = 160 -- <2> self.speed = 2 -- <3> self.t = 0 -- <4> end function update(self, dt) self.t = self.t + dt -- <5> local dx = math.sin(self.t * self.speed) * self.radius -- <6> local dy = math.cos(self.t * self.speed) * self.radius local pos = vmath.vector3() -- <7> pos.x = self.center.x + dx -- <8> pos.y = self.center.y + dy go.set_position(pos) -- <9> end --[[ 1. Store the center of rotation in the script instance (available through `self`). 2. Store the movement radius. 3. Store the movement speed. 4. Store the elapsed time, in seconds. 5. Increase the elapsed time with `dt`, the delta time elapsed since last call to `update()`. 6. Compute offsets along the X and Y axis. We're using `sinus` and `cosinus` of the current time, scaled with `self.speed`, which will plot points along a circle with radius `self.radius`. 7. Create a new `vector3` which will contain the computed position. 8. Set the `x` and `y` components of the vector to the rotation center plus offsets along X and Y axis. 9. Set the computed position on the current game object. --]] ``` # Modifiers {#examples:particles:modifiers} This example shows particle effect modifiers. Modifiers are used to alter the path of emitted particles. [Project files](https://github.com/defold/examples/tree/master/particles/modifiers) Here two modifiers are added to the effect in addition to the emitter. It works as follows: * The wide box emitter emits particles with a low speed. * The *Acceleration* modifier pushes the particles causing them to continuously speed up. * The *Vortex* modifier drags the particles into a vortex. Each particle's speed and direction is altered by the direction and magnitude of the vortex. The particle system features more modifier types so make sure to check them out. ## Scripts ### modifiers.script ```lua function init(self) particlefx.play("#particles") -- <1> end --[[ 1. Start playing the particle effect in component "particles" in this game object. --]] ``` # Particle effect {#examples:particles:particlefx} This example shows a simple particle effect. The particlefx component has all the values at default, except the image and animation used. [Project files](https://github.com/defold/examples/tree/master/particles/particlefx) ## Scripts ### particlefx.script ```lua function init(self) particlefx.play("#particles") -- <1> end --[[ 1. Start playing the particle effect in component "particles" in this game object. --]] ``` # Particle Effect Emission Space {#examples:particles:particlefx_emission_space} This example demonstrates the difference between local and world particle emission spaces. Two UFO objects move up and down, showing how particles behave differently when emitted in emitter space versus world space. [Project files](https://github.com/defold/examples/tree/master/particles/particlefx_emission_space) This example shows how particle emission space affects particle behavior when the emitter object moves. The setup consists of two UFO objects with identical particle effects, but different emission space settings. ## Setup The example collection consists of 2 game objects that differ only in the particlefx used: - particlefx on the left has `Emission Space` property set to `Emitter`: - particlefx on the right has `Emission Space` property set to `World`: Both game objects are animated up and down, so that you can see the difference between the emission space: ## How it works? Particles emitted in the **emitter** space are "moving" with the object, so their position is always respective to the emitter actual origin. Particles emitted in the **world** space have positions respective to the world coordinates. Use this example to understand when to use local or world emission space in your particle effects! ## Scripts ### particlefx.script ```lua function init(self) particlefx.play("#particles") -- <1> go.animate(".", "position.y", go.PLAYBACK_LOOP_PINGPONG, 500, go.EASING_INOUTSINE, 4) -- <2> end --[[ 1. Start playing the particle effect in component "particles" in this game object. 2. Animate this object position on Y axis up and down forever ]] ``` # Particle effect example - fire and smoke {#examples:particles:fire_and_smoke} This example shows a simple particle effect for imitating fire and smoke using two emitters and 3 modifiers in a single particlefx component. [Project files](https://github.com/defold/examples/tree/master/particles/fire_and_smoke) ## Setup The Particle Effect consists of two emitters: for fire and smoke. Each of them has tweaked properties. All combined creates a fire and smoke effect. There are also modifiers. Both emitter use a simple radial gradient blob image from sprites.atlas. Fire emitter is in front, because its Z position is 0.1, while smoke is at Z position equal to 0. There are two modifiers that affect both emitters: - Acceleration with Magnitude 70 +/- 10 - Radial with Magnitude: -30 +/- 40 positioned at Y = 150 Fire emitter has one additional modifier: - Vortex with Magnitude 0 +/- 50 - simulating random fluctuations of the fire effect. ### Fire properties Changed properties (from default): - Blend Mode: Alpha (for transparency blending) - Max Particle Count: 128 - Emitter Type: Circle - Spawn Rate: 35 +/- 10 - Emitter Size X: 100 +/- 20 (for circle emitters only Emitter Size X is taken into account, as radius) - Initial Speed: 30 +/- 20 - Initial Size: 80 +/- 10 - Initial Red: 1.0 - Initial Green: 0.5 +/- 0.1 - Initial Blue: 0.1 - Initial Alpha: 0.8 +/- 0.2 (for a little transparency) - Initial Rotation: 180 (to make flame sprite upside down) Additionally, the curves for Life Scale, Life Red, Life Green, and Life Alpha properties were adjusted: ### Smoke properties Smoke emitter has a smoke animation from sprites.atlas. It has two modifiers: - Acceleration with Magnitude 20 +/- 10 - Radial with Magnitude: -40 +/- 20 positioned at Y = 150 Changed properties (from default): - Position, Y: 60 (to emit a little bit above the fire) - Start Delay: 0.5 +/- 0.3 (to start a little bit after fire) - Blend Mode: Alpha (for transparency blending) - Max Particle Count: 32 - Emitter Type: Circle - Spawn Rate: 8 +/- 2 - Emitter Size X: 30 +/- 10 (for circle emitters only Emitter Size X is taken into account, as radius) - Particle Life Time: 5 +/- 0 - Initial Speed: 10 +/- 10 - Initial Size: 40 +/- 20 - Initial Alpha: 0.5 +/- 0.3 (for a lot of transparency) - Initial Rotation: 0 +/- 90 (to make intial rotation of smoke sprite random) Additionally, the curves for Life Scale, Life Red, Life Green, Life Alpha and Life Alpha properties were adjusted: The collection contains just a single game object with "particles" particlefx component and the script. ## Scripts ### fire_and_smoke.script ```lua function init(self) particlefx.play("#particles") -- <1> end --[[ 1. Start playing the particle effect in component "particles" in this game object. --]] ``` # ParticleFX - Confetti {#examples:particles:confetti} This example shows a simple particle effect to imitate confetti with multiple emitters and global multipliers for all of them. [Project files](https://github.com/defold/examples/tree/master/particles/confetti) In this example we create a confetti fireworks effect. It is usually used on final screens to congratulate the player on successful completion of a level or game. ## Setup The particlefx consists of 6 emitters. They are all the same, but with different images and RGB colors. It has two modifiers: - Acceleration to make the particles fly downwards, i.e. to simulate gravity. - Drag to slow down the initial speed of the particles. Changed properties (from default): - Blend Mode: Alpha for transparency blending - Max Particle Count: 8 to limit number of particles - Emitter Type: 2D Cone to set initial direction of the particles - Spawn Rate: 500 to spawn all particles at once - Emitter Size X: 100 +/- 20 - Initial Speed: 1500 +/- 300 to make particles fly upwards In addition, the curves for Life Scale, Life Alpha, Life Rotation properties have been adjusted to make the particles look like real confetti. The collection consists of the game object with the particle FX and script, and additional GUI to show instructions. ## How It Works The main script `confetti.script` spawns the particlefx on startup once, and each time when mouse button is clicked or screen touched. It also has a timer that spawns the particlefx in a loop with a 3 second delay. ## Scripts ### confetti.script ```lua local function single_shot() particlefx.play("#confetti") -- <1> end function init(self) single_shot() -- <2> timer.delay(3, true, single_shot) -- <3> msg.post(".", "acquire_input_focus") -- <4> end function on_input(self, action_id, action) if action_id == hash("mouse_button_left") and action.pressed then -- <5> single_shot() end end --[[ 1. Helper function `single_shot` starts playing the particle effect in component "confetti" in this game object. 2. Call it once in init. 3. Setup timer to do a single shot of confetti every 3 seconds. 4. Acquire input focus, so that we can detect clicks. 5. Play the effect when left mouse button (or touch) is pressed. --]] ``` # ParticleFX - Fountain - Start Delay {#examples:particles:particlefx_start_delay} This example shows how the Start Delay emitter property can be used to sequence two emitters inside a single ParticleFX and create a simple fountain effect. [Project files](https://github.com/defold/examples/tree/master/particles/particlefx_start_delay) This example shows how `Start Delay` can be used to coordinate multiple emitters inside a single ParticleFX. The effect is a simple fountain: one emitter shoots water droplets upward, and another emitter near the bottom creates a small splash when those droplets come back down. ## Setup The collection contains a single game object with: 1. ParticleFX component `#fountain` using `fountain.particlefx` 2. Script `fountain.script` that starts the effect in `init()` with `particlefx.play("#fountain")`. 3. GUI component `description` with text instructions. The particle effect itself contains two emitters: 1. The first emitter starts immediately and creates the main water jet. It is a narrow 2D cone with high initial speed, so the particles travel upward first. 2. The second emitter is placed lower, near the bottom of the fountain, and has `Start Delay` set to `1.8`. It uses a much wider emission shape and a shorter particle lifetime to create the impression of droplets bouncing and splashing when the first particles reach the basin area. A single `Acceleration` modifier with downward direction is shared by the whole effect. It pulls particles downward, simulating gravity, which makes the main jet arc back and helps the delayed splash particles fall off naturally. ## How It Works When the ParticleFX starts, the first emitter begins spawning droplets immediately. Because the particles are given a strong upward speed and are affected by downward acceleration, they rise, slow down, and then fall back. The second emitter does not emit right away. Its `Start Delay` is tuned so it begins around the same time the first droplets return to the bottom. This makes the splash feel connected to the main jet even though it is authored as a separate emitter. Using `Start Delay` this way is useful when one effect should have multiple phases, such as launch and impact, fire followed by smoke, or a fountain spray followed by a delayed splash, without having to coordinate several ParticleFX components from code. ## Scripts ### fountain.script ```lua function init(self) particlefx.play("#fountain") -- <1> msg.post(".", "acquire_input_focus") -- <2> end function on_input(self, action_id, action) if action_id == hash("mouse_button_left") and action.pressed then -- <3> particlefx.stop("#fountain", {clear = true}) -- <4> particlefx.play("#fountain") -- <5> end end --[[ 1. Start playing the particle effect in component "fountain" in this game object. 2. Acquire input focus, so that we can detect clicks. 3. When the left mouse button (or touch) is pressed: 4. Stop the currently played "fountain" particle FX with option `clear` set to true to remove all emitted particles. 5. Play the effect again. ]] ``` # ParticleFX emitter properties {#examples:particles:particlefx_set_get} This example shows how to get and set ParticleFX emitter image, animation, and material at runtime. [Project files](https://github.com/defold/examples/tree/master/particles/particlefx_set_get) Since Defold 1.12.2 you can use `go.get()` and `go.set()` on individual ParticleFX emitters by passing `keys = { "..." }`. This example focuses on this feature. It toggles a ParticleFX between two setups and shows the properties of the active emitters in the labels. ## Setup 1. Example consists of one game object in the collection having: - script `particlefx_set_get.script` - ParticleFX component named `#particles` - 2 label components: `#label_core` and `#label_spark` 2. The ParticleFX: - has two emitters: `emitter_top` and `emitter_bottom` 3. The script has the resources exposed as properties: - `particles_atlas` - `sprites_atlas` - `default_material` - `glow_material` The current script switches the emitter `image` directly from code and keeps `default_material` active for the shown setup. 4. The example uses 2 atlases with given animations: - the `particles.atlas` with `coin` and `smoke` animations - the `sprites.atlas` with `ship_red` and `ship_dark` animations The atlases are set up to contain the animation ids used by the script, so the example can switch between the two setups without extra transition logic. It would also be possible to read the animations from `resource.get_atlas()`, but this example keeps a small hardcoded `ANIMATIONS` table to stay as simple as possible. ## How it works The script keeps two hardcoded setups and toggles between them whenever you click or tap: 1. `particles.atlas` + default particle material `emitter_top` uses `coin` `emitter_bottom` uses `smoke` 2. `sprites.atlas` + default particle material `emitter_top` uses `ship_red` `emitter_bottom` uses `ship_dark` On startup the script stores the current atlas name, reads back the authored emitter properties, writes them into the labels, and starts the ParticleFX. When the setup changes after that, the script: 1. stops the ParticleFX with `{ clear = true }` 2. flips `self.atlas_name` between `sprites_atlas` and `particles_atlas` 3. looks up the atlas resource and the correct animation pair from the `ANIMATIONS` table 4. calls `set_emitter_properties()` for each emitter to set `image`, `animation`, and `material` 5. calls `get_and_print_emitter_properties()` to read the current values back with `go.get()` 6. writes them into the two labels 7. plays the ParticleFX again The helper function `set_emitter_properties()` applies properties per emitter by passing the emitter id in `keys`: ```lua go.set("#particles", "image", image, { keys = { "emitter_top" } }) go.set("#particles", "animation", animation, { keys = { "emitter_top" } }) go.set("#particles", "material", material, { keys = { "emitter_top" } }) ``` The helper function `get_and_print_emitter_properties()` uses the same `keys` pattern with `go.get()` and writes the result into the labels, so the example shows which values are currently active for each emitter. One important limitation: **emitter property changes only affect the next play**. The script therefore stops the ParticleFX, clears any already spawned particles, applies the new emitter overrides, and then plays it again. ## Scripts ### particlefx_set_get.script ```lua -- Properties - 2 atlases: go.property("particles_atlas", resource.atlas("/assets/particles.atlas")) go.property("sprites_atlas", resource.atlas("/assets/sprites.atlas")) -- Properties - 2 materials: go.property("default_material", resource.material("/builtins/materials/particlefx.material")) go.property("glow_material", resource.material("/example/particlefx_glow.material")) -- Predefined table with animations for given atlases: -- (One can get the animations from resource.get_atlas() too) local ANIMATIONS = { ["particles_atlas"] = { hash("coin"), hash("smoke") }, ["sprites_atlas"] = { hash("ship_red"), hash("ship_dark") } } -- Relative address of the particlefx component: local PARTICLEFX = "#particles" -- Read the current emitter properties back from the particlefx component -- and show them in the on-screen labels. local function get_and_print_emitter_properties(emitter, url) -- Get the properties of the emitter: local image = go.get(PARTICLEFX, "image", { keys = { emitter } }) local animation = go.get(PARTICLEFX, "animation", { keys = { emitter } }) local material = go.get(PARTICLEFX, "material", { keys = { emitter } }) -- Show the properties in the label: label.set_text(url, emitter .. ":\nimage: " .. image .. "\nanimation: " .. animation .. "\nmaterial: " .. material ) end -- Apply one full property set to a single emitter. local function set_emitter_properties(emitter, image, animation, material) go.set(PARTICLEFX, "image", image, { keys = { emitter } }) go.set(PARTICLEFX, "animation", animation, { keys = { emitter } }) go.set(PARTICLEFX, "material", material, { keys = { emitter } }) end -- Toggle between the two hardcoded setups: -- particles atlas + glow material, or sprites atlas + default material. local function change_particlefx_properties(self) -- Stop the particlefx before swapping atlas/material overrides. particlefx.stop(PARTICLEFX, { clear = true }) -- Swap the atlas name and material: if self.atlas_name == "sprites_atlas" then self.atlas_name = "particles_atlas" self.material = self.glow_material else self.atlas_name = "sprites_atlas" self.material = self.default_material end -- Get current atlas resource and animations set for it: local atlas = self[self.atlas_name] local animations = ANIMATIONS[self.atlas_name] -- Set the atlas, animation and material for each emitter: set_emitter_properties("emitter_top", atlas, animations[1], self.material) set_emitter_properties("emitter_bottom", atlas, animations[2], self.material) -- Get the current properties and print them in the label for each emitter: get_and_print_emitter_properties("emitter_top", "#label_core") get_and_print_emitter_properties("emitter_bottom", "#label_spark") -- Play the particlefx again: particlefx.play(PARTICLEFX) end function init(self) -- Acquire input focus to react to the mouse click/touch: msg.post(".", "acquire_input_focus") -- Initialize the atlas name: self.atlas_name = "sprites_atlas" self.material = self.default_material -- Get the current properties and print them in the label for each emitter: get_and_print_emitter_properties("emitter_top", "#label_core") get_and_print_emitter_properties("emitter_bottom", "#label_spark") -- Start the ParticleFX: particlefx.play(PARTICLEFX) end function on_input(self, action_id, action) -- Toggle the setup on touch release: if action_id == hash("touch") and action.released then change_particlefx_properties(self) end end ``` ### particlefx_glow.fp ```glsl #version 140 in mediump vec2 var_texcoord0; in mediump vec4 var_color; out vec4 out_fragColor; uniform mediump sampler2D texture_sampler; uniform fs_uniforms { mediump vec4 tint; }; void main() { mediump vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w); mediump vec4 base = texture(texture_sampler, var_texcoord0.xy) * var_color * tint_pm; mediump float energy = max(max(base.r, base.g), base.b); mediump vec3 glow = vec3(0.9, 1.4, 1.8) * energy; out_fragColor = vec4(base.rgb * 0.2 + glow, base.a); } ``` # Spawning Fireworks ParticleFX {#examples:particles:fireworks} This example shows how to spawn firework rockets with separate trail and burst particle effects, including a small dip before the burst. [Project files](https://github.com/defold/examples/tree/master/particles/fireworks) ## Setup The collection contains: - one controller game object with `fireworks.script`; - six embedded factories: one `trail` factory and one `splat` factory for each of the three colors; - one GUI component that shows the click/tap instruction on screen. Each firework is built from two separate particlefx game objects: - a looping `trail` effect that represents the rocket while it is flying; - a one-shot `splat` effect that represents the explosion at the end. The script does not use `update()`. It spawns the trail object, animates it with `go.animate()`, and starts the burst effect from the animation callback when the flight finishes. ## Trail particlefx Each `trail` particlefx file contains one looping cone emitter. The three color variants share the same setup and only differ in their base RGB values. The trail emitter uses: - `Emmision Space` : `World`, so emitted particles stay behind in world space instead of following the moving game object; - `Particle Orientation` : `Movement direction`; - additive blending; - the `fw_circle_01` sprite from `/assets/sprites.atlas`; - a spawn rate of `64`, particle lifetime `0.6`, and particle size around `40` with a small spread. Because the sprite is a soft circle rather than a directional streak, the trail reads more like a glowing puff stream than a sharp rocket spark. The scale and alpha curves in the emitter make each particle start fairly full, then shrink and fade out quickly. The trail game object itself is prepared by the script before the animation starts: - position is set near the bottom of the screen; - scale is animated down over time so the trail feels like it is burning out before the explosion. ## Burst particlefx Each `splat` particlefx file is a one-shot layered burst built from five circle emitters. The red, green and blue files use the same emitter structure and timings, with color values changed per variant. The five burst layers are: - a `fw_trace_01` streak layer with movement-direction orientation, about `64` particles, lifetime around `1.6`, speed around `200`, and velocity stretching; - a `fw_star_01` star layer with angular-velocity orientation, about `30` particles, lifetime around `1.6`, speed around `300`, and randomized rotation; - a second `fw_trace_01` streak layer with additive blending for extra brightness; - a `fw_light_01` flash layer that emits a single large soft light particle; - a second additive `fw_light_01` layer that adds a smaller glow on top of the main flash. The moving burst layers also use modifiers. The streak layers use acceleration, and the star and additive streak layers also use radial shaping, so the burst does not expand as a perfectly uniform circle. The two `fw_light_01` emitters do not throw particles outward; they behave more like expanding flashes at the center of the explosion. Like the trail, the burst emitters also use `Emmision Space` : `World`, so the explosion stays fixed at the burst position after it has been spawned. ## Script and spawning The script handles spawning in three ways: - it launches one firework in `init()`; - it starts a repeating timer that launches another firework every 3 seconds; - it launches another firework when the left mouse button is pressed, which also works as click/tap input in the example. To keep the effect under control, the script allows at most 16 active fireworks at the same time. `spawn_firework()` first checks that limit. It then: - picks a random color from `red`, `green` and `blue`; - creates the matching trail and burst game objects with `factory.create()`; - generates a random launch angle, launch strength and flight time; - computes the initial position near the bottom of the screen, a peak position, and a burst position slightly below that peak; - starts the trail particlefx; - starts `go.animate()` for `position.x`, `position.y` and `scale`. The values that control this motion are collected at the top of the script, including: - launch strength and angle range; - start position and horizontal spread; - flight time and flight-distance ratio; - how much of the total flight is used for the final dip; - the minimum and maximum distance of that dip. The rocket flight uses two separate property animations: - `position.x` uses linear easing; - `position.y` first uses `go.EASING_OUTQUAD` to rise to the peak, then `go.EASING_INQUAD` to dip slightly before the burst; - `scale` is animated down during the flight. Using different easing for X and Y gives a simple curved flight path without a manual simulation loop. Splitting the Y animation into two phases lets the rocket rise, dip a little, and then explode. When the second Y animation finishes, its completion callback stops and deletes the trail object, reads its final position, and plays the burst effect there. A separate one-shot timer then deletes the burst object after a short cleanup delay. To reuse this setup in another project: - add factories for the trail and burst particlefx game objects; - spawn both objects with `factory.create()`; - choose a start position, a target position and a flight time; - animate the trail object with `go.animate()`; - trigger and clean up the burst effect from the animation callback. Particle sprites are CC0 from Kenney Particle Pack. ## Scripts ### fireworks.script ```lua local COLORS = { "red", "green", "blue" } local MAX_ACTIVE_FIREWORKS = 8 local AUTO_LAUNCH_DELAY = 3 local BURST_CLEANUP_DELAY = 1.5 local LAUNCH_STRENGTH_MIN = 400 local LAUNCH_STRENGTH_RANGE = 300 local LAUNCH_ANGLE_MIN = -0.28 * math.pi local LAUNCH_ANGLE_RANGE = 0.56 * math.pi local START_POSITION_X = 360 local START_POSITION_Y = 0 local START_POSITION_SPREAD = 350 local FLIGHT_TIME_MIN = 1.2 local FLIGHT_TIME_RANGE = 0.5 local FLIGHT_DISTANCE_RATIO = 0.55 local FALL_PHASE_RATIO = 0.2 local FALL_DISTANCE_MIN = 5 local FALL_DISTANCE_MAX = 35 local TRAIL_END_SCALE = 0.2 local active_fireworks = 0 -- <1> local function delete_burst(burst_id) go.delete(burst_id) -- <2> active_fireworks = active_fireworks - 1 -- <3> end local function burst_firework(trail_id, burst_id) local position = go.get_position(trail_id) -- <4> particlefx.stop(trail_id, { clear = true }) -- <5> go.delete(trail_id) -- <6> go.set_position(position, burst_id) -- <7> particlefx.play(burst_id) -- <8> timer.delay(BURST_CLEANUP_DELAY, false, function() -- <9> delete_burst(burst_id) end) end local function spawn_firework() if active_fireworks >= MAX_ACTIVE_FIREWORKS then -- <10> return end local color = COLORS[math.random(#COLORS)] -- <11> local trail_id = factory.create("#" .. color .. "_trail_factory") -- <12> local burst_id = factory.create("#" .. color .. "_splat_factory") -- <13> local launch_strength = LAUNCH_STRENGTH_MIN + math.random() * LAUNCH_STRENGTH_RANGE -- <14> local launch_angle = LAUNCH_ANGLE_MIN + math.random() * LAUNCH_ANGLE_RANGE -- <15> local start_position = vmath.vector3(START_POSITION_X - math.sin(launch_angle) * START_POSITION_SPREAD, START_POSITION_Y, 0) -- <16> local flight_time = FLIGHT_TIME_MIN + math.random() * FLIGHT_TIME_RANGE -- <17> local velocity = vmath.vector3(launch_strength * math.sin(launch_angle), launch_strength * math.cos(launch_angle), 0) local peak_position = start_position + velocity * flight_time * FLIGHT_DISTANCE_RATIO -- <18> local fall_distance = FALL_DISTANCE_MIN + math.random() * (FALL_DISTANCE_MAX - FALL_DISTANCE_MIN) local end_position = peak_position - vmath.vector3(0, fall_distance, 0) local rise_time = flight_time * (1 - FALL_PHASE_RATIO) local fall_time = flight_time * FALL_PHASE_RATIO go.set_position(start_position, trail_id) -- <19> particlefx.play(trail_id) -- <20> active_fireworks = active_fireworks + 1 -- <21> go.animate(trail_id, "position.x", go.PLAYBACK_ONCE_FORWARD, end_position.x, go.EASING_LINEAR, flight_time) -- <22> go.animate(trail_id, "position.y", go.PLAYBACK_ONCE_FORWARD, peak_position.y, go.EASING_OUTQUAD, rise_time, 0, function() go.animate(trail_id, "position.y", go.PLAYBACK_ONCE_FORWARD, end_position.y, go.EASING_INQUAD, fall_time, 0, function() -- <23> burst_firework(trail_id, burst_id) -- <24> end) end) go.animate(trail_id, "scale", go.PLAYBACK_ONCE_FORWARD, TRAIL_END_SCALE, go.EASING_INQUAD, flight_time) -- <25> end function init(self) spawn_firework() -- <26> timer.delay(AUTO_LAUNCH_DELAY, true, spawn_firework) -- <27> msg.post(".", "acquire_input_focus") -- <28> end function on_input(self, action_id, action) if action_id == hash("mouse_button_left") and action.pressed then spawn_firework() -- <29> end end --[[ 1. Keep a count of active fireworks so no more than 16 are running at once. 2. Delete the burst game object after its cleanup delay has finished. 3. Free one active firework slot when the burst object is removed. 4. Read the trail object's current position so the burst can be played there. 5. Stop the trail particle effect and clear already emitted particles when the flight ends. 6. Delete the trail game object once it has finished flying. 7. Move the burst object to the trail object's last position. 8. Play the burst particle effect at that position. 9. Start a one-shot timer that cleans up the burst after a short delay. 10. Stop spawning if the maximum number of active fireworks is already on screen. 11. Pick one of the available firework colors. 12. Create the trail game object for that color. 13. Create the burst game object for that color. 14. Randomize the launch strength so different rockets travel different distances. 15. Randomize the launch angle so the fireworks spread out across the screen. 16. Compute a start position near the bottom edge, offset by the launch angle. 17. Randomize how long the rocket flight lasts before it bursts. 18. Compute a peak position for the rocket, then offset the burst point downward so it dips a bit before exploding. 19. Place the trail object at the launch position. 20. Start the trail particle effect. 21. Reserve one active firework slot for this spawned rocket. 22. Animate the rocket horizontally with linear easing. 23. Animate the rocket upward first, then run a short downward animation before bursting. 24. Start the burst effect when the flight animation finishes. 25. Animate the rocket scale down over time so the trail looks like it is burning out. 26. Launch one firework immediately when the example starts. 27. Start a repeating timer that spawns another firework every 3 seconds. 28. Acquire input focus so the script can react to click or tap input. 29. Launch another firework when the left mouse button or a touch press is detected. ]] ``` # Apply force {#examples:physics:apply_force} This example demonstrates how to apply directional force to all dynamic blocks on touch/click and draws debug direction lines. [Project files](https://github.com/defold/examples/tree/master/physics/apply_force) This example demonstrates how to apply directional force to all dynamic blocks on touch/click and draws debug direction lines. ## Setup Scene consists of a few game objects: - `controller` - Main object that contains `/example/apply_force.script` and a label with usage text. - `block1`, `block2`, `block3`, `block4` - Dynamic rigid bodies (sprite + dynamic collision object). - `walls` - Static boundary collision object around the screen. Proposed settings regarding physics in the `game.project` file: ## Script flow A single controller script handles input for the whole scene. When you touch/click, it loops over all dynamic blocks, computes a force vector for each one, applies the force, and draws a debug line that visualizes the direction. 1. acquires input focus in `init()` 2. listens to `hash("touch")` in `on_input()` 3. iterates over all block ids 4. computes `force = (touch - center) * force_factor` 5. posts `apply_force` to each block 6. posts `@render: draw_line` for debug visualization ## Scripts ### apply_force.script ```lua -- Multiplier applied to the touch->block direction vector. local force_factor = 30 -- Debug line color used by @render:draw_line. local debug_line_color = vmath.vector4(0, 0.5, 1, 1) -- Game object ids of dynamic blocks controlled by this script. -- The script is attached to the "controller" object in the collection. local blocks = { [1] = "block1", [2] = "block2", [3] = "block3", [4] = "block4", } function init(self) -- <1> Receive touch/mouse input in on_input(). msg.post(".", "acquire_input_focus") end -- Pre-hashed action id for the touch action. local touch_action_id = hash("touch") function on_input(self, action_id, action) -- <2> Built-in "touch" also maps mouse clicks on desktop. if action_id == touch_action_id then -- <3> Iterate over all blocks and apply force to each. for _, block in pairs(blocks) do -- <4> Compute the force vector by subtracting the block center from the touch position. local center = go.get_world_position(block) local touch = vmath.vector3(action.x, action.y, center.z) local force = (touch - center) * force_factor -- <5> Send force to the block's dynamic collision object. msg.post(block, "apply_force", { force = force, position = center }) -- <6> Visualize direction from touch point to block center. msg.post("@render:", "draw_line", { start_point = touch, end_point = center, color = debug_line_color }) end end end function final(self) -- Stop receiving input when the controller is destroyed. msg.post(".", "release_input_focus") end ``` # Dynamic physics {#examples:physics:dynamic} This example shows a simple setup with dynamic physics objects. [Project files](https://github.com/defold/examples/tree/master/physics/dynamic) The setup consists of three game objects. The *game.project* physics *GravityY* property is set to -500 to match the scale of the setup. block1 : The rectangular stone block. Contains: - A *Sprite* component with the stone block image. - A *Collision object* component. The *Type* is set to `DYNAMIC`, *Friction* is set to 0 and *Restitution* to 1.0 (it will bounce forever). A box *Shape* matching the sprite image is added to the components. block2 : The square stone block. Contains: - A *Sprite* component with the stone block image. - A *Collision object* component. Also has *Type* set to `DYNAMIC`, *Friction* set to 0 and *Restitution* to 1.0. A box *Shape* matching the sprite image is added to the components. walls : The outer walls. Contains: - A *Collision object* component. The *Type* is set to `STATIC`. 4 box *Shapes* are added to the component. These are placed just outside of the game view. # Fixed timestep interpolation {#examples:physics:interpolation} This example shows how to smooth physics motion in fixed update mode by interpolating a visual sprite while keeping the physics body fixed-step. [Project files](https://github.com/defold/examples/tree/master/physics/interpolation) This example demonstrates two rendering paths while physics runs at a fixed frequency: - `Not interpolated`: visual sprite follows the dynamic body directly (visually looks like it has a stepped motion). - `Interpolated`: visual sprite is interpolated between fixed physics states (smooth motion). The key idea is to separate physics simulation from rendering: - Keep the transforms of the game objects with dynamic collision objects as the source of truth. - Set position of the visual representation based on the position of the physics objects. - Interpolate only the visual representation transform. ## Setup In `game.project`: 1. In the `Physics` section set `Use_Fixed_Timestep` enabled and `Velocity Threshold` to 50 (It is necessary for 2D physics, because velocity threshold is scaled with the scale option, and in the end it should be 1.0 internally in Box2D, so if Scale is set to 0.02, the velocity threshold should be 50 = 1.0 / 0.02). Gravity is set arbitraly for this example to -500. 2. In the `Engine` section set `Fixed Update Frequency` to a low value, e.g. 20, so the difference is easy to see. The setup consists of 5 game objects: `walls` : Static borders and the script host. - A static *Collision object* component. - A script component using `/example/interpolation.script`. `block1` : Game Object for the non-interpolated path for the physics component. - A dynamic *Collision object* component. - No sprite (physics-only object). `block1_sprite` : Game Object for the non-interpolated path for the visual representation. - A *Sprite* component. - A *Label* component (with text `Not interpolated`). `block2` : Game Object for the interpolated path for the physics component. - A dynamic *Collision object* component. - No sprite (physics-only object). `block2_sprite` : Game Object for the non-interpolated path for the visual representation. - A *Sprite* component. - A *Label* component (with text `Interpolated`). ## Script Behavior `/example/interpolation.script`: 1. Keeps a two-sample fixed-state buffer for `block2`: - `previous` = previous fixed physics sample - `current` = current fixed physics sample 2. In `fixed_update()`, shifts values (`current` data becomes `previous` data) and samples a new `current` transform from the objects controlled by the dynamic collision objects. 3. In `update()`, computes render progress inside the current fixed interval: - `alpha = render_accumulator / fixed_dt` 4. Renders: - `block1_sprite` from raw `block1` transform. - `block2_sprite` from interpolated transform (position is interpolated using `vmath.lerp()`, and rotation is interpolated using `vmath.slerp()`). ## Expected Result At runtime: - `block1_sprite` appears updated at the fixed frequency. - `block2_sprite` appears updated each frame. ## Scripts ### interpolation.script ```lua -- This example compares two render paths when physics runs in fixed timestep mode: -- 1) not_interpolated_block: visual representation copies physics representation transform directly local not_interpolated_block = { physics_go = "/block1", sprite_go = "/block1_sprite", } -- 2) interpolated_block: visual representation is interpolated between previous and current fixed states local interpolated_block = { physics_go = "/block2", sprite_go = "/block2_sprite", } -- Store fixed update interval in seconds from game.project Fixed Update Frequency. local fixed_dt = 1 / (sys.get_config_number("engine.fixed_update_frequency") or 20) function init(self) -- Render-time remainder inside the current fixed-step interval. self.render_accumulator = 0 -- Two-sample buffer for interpolation: -- previous_* = transform from previous fixed update -- current_* = transform from current fixed update -- Initialize both from real physics representation state. self.previous_fixed_position = go.get_position(interpolated_block.physics_go) self.current_fixed_position = self.previous_fixed_position self.previous_fixed_rotation = go.get_rotation(interpolated_block.physics_go) self.current_fixed_rotation = self.previous_fixed_rotation end function fixed_update(self, dt) -- Shift the transform data from current state to previous state -- and sample new fixed state from the game object with the dynamic collision object component. self.previous_fixed_position = self.current_fixed_position self.previous_fixed_rotation = self.current_fixed_rotation self.current_fixed_position = go.get_position(interpolated_block.physics_go) self.current_fixed_rotation = go.get_rotation(interpolated_block.physics_go) end function update(self, dt) ------------------------------------------------------------------------------------- -- For not interpolated object: ------------------------------------------------------------------------------------- -- Copy physics transform directly to the visual representation. local not_interpolated_position = go.get_position(not_interpolated_block.physics_go) local not_interpolated_rotation = go.get_rotation(not_interpolated_block.physics_go) go.set_position(not_interpolated_position, not_interpolated_block.sprite_go) go.set_rotation(not_interpolated_rotation, not_interpolated_block.sprite_go) ------------------------------------------------------------------------------------- -- For interpolated object: ------------------------------------------------------------------------------------- -- Keep accumulator inside [0, fixed_dt) using modulo wrap. self.render_accumulator = math.fmod(self.render_accumulator + dt, fixed_dt) -- Base alpha from render progress between fixed samples: -- alpha=0 -> previous sample, alpha=1 -> current sample. local alpha = self.render_accumulator / fixed_dt -- Calculate the difference between the current and previous fixed positions. local position_difference = self.current_fixed_position - self.previous_fixed_position -- Position interpolation is linear (lerp). local interpolated_position = self.previous_fixed_position + position_difference * alpha -- Rotation interpolation is spherical (slerp). local interpolated_rotation = vmath.slerp(alpha, self.previous_fixed_rotation, self.current_fixed_rotation) -- Render blended transform. go.set_position(interpolated_position, interpolated_block.sprite_go) go.set_rotation(interpolated_rotation, interpolated_block.sprite_go) end ``` # Hinge joint physics {#examples:physics:hinge_joint} This example shows a simple setup with a dynamic body physics object and two dynamic wheel physics object joined together with a joint of type "hinge". The hinge joint can simulate an axle or a pin on which other object is rotating in respect to the base. The example shows how to create, destroy and change properties of the joints. [Project files](https://github.com/defold/examples/tree/master/physics/hinge_joint) The setup consists of four game objects. The *game.project* physics *GravityY* property is set to -500 to match the scale of the setup. body : The square stone block. Contains: - A *Sprite* component with the stone block image. - A *Collision object* component. The *Type* is set to `DYNAMIC`. A box *Shape* matching the sprite image is added to the components. - A script that joines the wheel game objects to to the body and reacts to user input by changing the direction of the rotation of the hinge joints. - A label with an instruction to the user. frontwheel : The cirular metal wheel. Contains: - A *Sprite* component with the metal circle image. - A *Collision object* component. Also has *Type* set to `DYNAMIC`, *Friction* set to 0.9 and *Restitution* to 0.1. A box *Shape* matching the sprite image is added to the components. backwheel : The same as above. walls : The outer walls. Contains: - A *Collision object* component. The *Type* is set to `STATIC`. 4 box *Shapes* are added to the component. These are placed just outside of the game view. ## Scripts ### hinge_joint.script ```lua local frontwheel = "frontwheel#collisionobject" -- <1> local backwheel = "backwheel#collisionobject" local body = "body#collisionobject" local center_anchor = vmath.vector3(0, 0, 0) local frontwheel_anchor = vmath.vector3(60, -60, 0) local backwheel_anchor = vmath.vector3(-60, -60, 0) local hinge_props = { enable_motor = true, enable_limit = false, max_motor_torque = 3000, motor_speed = 1 * 2 * math.pi} function init(self) msg.post(".", "acquire_input_focus") -- <2> self.forward = true -- <3> physics.create_joint(physics.JOINT_TYPE_HINGE, frontwheel, "frontwheel", center_anchor, body, frontwheel_anchor, hinge_props) -- <4> physics.create_joint(physics.JOINT_TYPE_HINGE, backwheel, "backwheel", center_anchor, body, backwheel_anchor, hinge_props) end function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed then -- <5> self.forward = not self.forward -- <6> if self.forward then -- <7> hinge_props.motor_speed = 5 * 2 * math.pi -- <8> else -- <9> hinge_props.motor_speed = -5 * 2 * math.pi -- <10> end physics.set_joint_properties(frontwheel, "frontwheel", hinge_props) -- <11> physics.set_joint_properties(backwheel, "backwheel", hinge_props) end end --[[ 1. Store collision objects ids, vectors used for anchors and hinge properties used for creating joints in local variables. 2. Tell the engine that this object ("." is shorthand for the current game object) should listen to input. Any input will be received in the `on_input()` function. 3. Set a flag self.forward used to define the direction of the rotation of the joined wheels. 4. Create a joint of type "hinge" (a revolute joint, a pin or an axle) between a center of frontwheel collision object and an anchor ((-60,-60) from the center) on body collision object with provided properties. Do the same for the second wheel. 5. If we receive input (touch or mouse click) we switch the direction of rotation of the wheels. 6. Negate the current flag defining the direction. 7. If the direction flag is true, we are going forward. 8. Set the motor_speed property to 5 revolutions per second in clockwise direction. 9. If the direction flag is false, we are going backward. 10. Set the motor_speed property to 5 revolutions per second in counter-clockwise direction. 11. Set the new properties with changed speed for the joints. --]] ``` # Kinematic physics {#examples:physics:kinematic} This example shows a simple setup with a kinematic physics objects. The difference between dynamic objects, simulated by the physics engine, and kinematic objects, that are user controlled, is clearly seen here. [Project files](https://github.com/defold/examples/tree/master/physics/kinematic) The setup consists of three game objects. The *game.project* physics *GravityY* property is set to -500 to match the scale of the setup. block : The square stone block. Contains: - A *Sprite* component with the stone block image. - A *Collision object* component. The *Type* is set to `KINEMATIC`. A box *Shape* matching the sprite image is added to the components. - A script that moves the game object to where the user clicks. block2 : The rectangular stone block. Contains: - A *Sprite* component with the stone block image. - A *Collision object* component. Also has *Type* set to `DYNAMIC`, *Friction* set to 0 and *Restitution* to 1.0. A box *Shape* matching the sprite image is added to the components. walls : The outer walls. Contains: - A *Collision object* component. The *Type* is set to `STATIC`. 4 box *Shapes* are added to the component. These are placed just outside of the game view. ## Scripts ### kinematic.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> self.moving = false -- <2> end local function landed(self) -- <9> self.moving = false end function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed then -- <3> if not self.moving then -- <4> msg.post("#label", "disable") -- <5> self.moving = true -- <6> pos = vmath.vector3(action.x, action.y, 0) -- <7> go.animate(".", "position", go.PLAYBACK_ONCE_FORWARD, pos, go.EASING_LINEAR, 0.5, 0, landed) -- <8> end end end --[[ 1. Tell the engine that this object ("." is shorthand for the current game object) should listen to input. Any input will be received in the `on_input()` function. 2. Store a flag in `self` (the current script component) to indicate if the game object is moving or not. 3. If we receive an input action named "touch" and it is pressed then run the following. 4. If the `moving` flag is not set. 5. Disable (don't show) the help text label. 6. Set the `moving` flag. 7. Create a new position called `pos` (of type `vector3`) where the user clicked. 8. Animate the game object's ("." is shorthand for the current game object) position to `pos`. When the animation is done, call the function `landed()`. 9. The function `landed()` is called when the animation is done. It just resets the `moving` flag so subsequent clicks will result in a new movement. --]] ``` # Knockback {#examples:physics:knockback} This example shows how to create a knockback effect when hit. [Project files](https://github.com/defold/examples/tree/master/physics/knockback) This example shows how to create a knockback effect when hit. The setup consists of three game objects; one for the player, one for the enemy and one for the bullet that is spawned using a factory (see example on how to spawn bullets). player : The red ship at the bottom. Contains: - A *Sprite* component with the spaceship image. - A *Factory* component to spawn bullet game objects - A script to handle spawning of bullets. bullet : The bullet fired by the player. Contains: - A *Sprite* component with a bullet image. - A *Collision object* component. *Type* is set to `KINEMATIC`. It has a sphere *Shape* matching image. enemy : The black ship at the top. Contains: - A *Sprite* component with the spaceship image. - A *Collision object* component. *Type* is set to `KINEMATIC`. It has a sphere *Shape* matching image. - A script to handle collisions with bullets. ## Scripts ### enemy.script ```lua -- move game object back and forth from the current position to a target position local function move() local pos = go.get_position() local to = vmath.vector3(pos.x, 300, 0) local distance = pos.y - to.y local speed = 40 local duration = distance / speed go.animate(".", "position", go.PLAYBACK_LOOP_PINGPONG, to, go.EASING_INOUTQUAD, duration) end function init(self) move() end function on_message(self, message_id, message, sender) if message_id == hash("contact_point_response") then if message.other_group == hash("bullet") then -- delete the bullet go.delete(message.other_id) -- get the position of the game object local pos = go.get_position() -- set a pushback direction based on the collision normal local to = pos + message.normal * 30 -- knockback animation, then continue moving go.animate(".", "position", go.PLAYBACK_ONCE_FORWARD, to, go.EASING_OUTQUAD, 0.1, 0, move) end end end ``` # Pendulum physics {#examples:physics:pendulum} This example shows a simple setup with a static pivot and two dynamic weights - physics objects joined together with a joint of type "fixed" and "spring". The fixed joint can simulate a rope and spring joint a spring. The example shows how to create the joints and change the gravity to affect the pendulums. [Project files](https://github.com/defold/examples/tree/master/physics/pendulum) The setup consists of four game objects. The *game.project* physics *GravityY* property is set to -500 to match the scale of the setup. pivot : The square stone block. Contains: - A *Sprite* component with the stone block image. - A *Collision object* component. The *Type* is set to `STATIC`. A box *Shape* matching the sprite image is added to the components. - A script that joines the weights game objects to to the pivot and reacts to user input by changing the direction of the physics gravity. - A label with an instruction to the user. weight_fixed : The cirular metal weight. Contains: - A *Sprite* component with the metal circle image. - A *Collision object* component. Also has *Type* set to `DYNAMIC`. A box *Shape* matching the sprite image is added to the component. weight_spring : The same as above. walls : The outer walls. Contains: - A *Collision object* component. The *Type* is set to `STATIC`. 4 box *Shapes* are added to the component. These are placed just outside of the game view. ## Scripts ### pendulum.script ```lua local function draw_line(from, to) msg.post("@render:", "draw_line", { start_point = from, end_point = to, color = vmath.vector4(1,0,0,1) }) -- <1> end function init(self) msg.post(".", "acquire_input_focus") -- <2> self.gravity = physics.get_gravity() -- <3> self.pivot_pos = go.get_position() -- <4> local center_anchor = vmath.vector3(0, 0, 0) -- <5> local pivot = "pivot#collisionobject" local weight_fixed = "weight_fixed#collisionobject" local weight_spring = "weight_spring#collisionobject" physics.create_joint(physics.JOINT_TYPE_FIXED, weight_fixed, "weight_fixed_joint", center_anchor, pivot, center_anchor, {max_length = 250}) -- <6> physics.create_joint(physics.JOINT_TYPE_SPRING, weight_spring, "weight_spring_joint", center_anchor, pivot, center_anchor, {length = 150, frequency = 1, damping = 0}) -- <7> end function update(self, dt) local weight_pos = go.get_position("/weight_fixed") -- <8> local weight1_pos = go.get_position("/weight_spring") draw_line(self.pivot_pos, weight_pos) -- <9> draw_line(self.pivot_pos, weight1_pos) end function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed then -- <10> if self.gravity.y ~= 0 then -- <11> self.gravity.y = 0 self.gravity.x = 500 else self.gravity.y = -500 self.gravity.x = 0 end physics.set_gravity(self.gravity) -- <12> end end --[[ 1. Helper function to draw a line between two points. 2. Tell the engine that this object ("." is shorthand for the current game object) should listen to input. Any input will be received in the `on_input()` function. 3. Get current physics gravity vector and store it in self reference to change it later. 4. Get current position of the pivot and store it in self reference for drawing a line between the pivot and weights. 5. Store vector used for anchoring joints and collision objects ids in local variables for ease of use in below function. 6. Create a fixed joint between a first weight and the pivot 7. create a spring type joing between the second weight and the pivot. 8. Get updated positions of both weights. 9. Draw lines between the weights and the pivot. 10. If we receive input (touch or mouse click) we switch the direction of the gravity pull. 11. If the gravity is set to the bottom of the screen, set it so it pulls to the right, in other case, set it back to pull to the bottom. 12. Set the new gravity vector. --]] ``` # Raycast {#examples:physics:raycast} This example shows how to use physics raycasts to detect collisions along a straight line from a start point to an end point. [Project files](https://github.com/defold/examples/tree/master/physics/raycast) The setup consists of two different kinds of game objects. bee : The bee. Contains: - A *Sprite* component with the bee image. - A script that performs raycasts from the game object position to the position of mouse/touch input. stone : The square stone block. Contains: - A *Sprite* component with the stone block image. - A *Collision object* component with a group set to `stone`. ## Scripts ### raycast.script ```lua local function draw_line(from, to) msg.post("@render:", "draw_line", { start_point = from, end_point = to, color = vmath.vector4(1,0,0,1) }) end function init(self) msg.post(".", "acquire_input_focus") -- <1> self.to = vmath.vector3() -- <2> end function update(self, dt) local from = go.get_position() local to = self.to local result = physics.raycast(from, to, { hash("stone") }) -- <4> if result then draw_line(from, result.position) -- <5> else draw_line(from, to) -- <6> end end function on_input(self, action_id, action) if not action_id or action_id == hash("touch") then -- <3> self.to.x = action.x self.to.y = action.y end end --[[ 1. Tell the engine that this object ("." is shorthand for the current game object) should listen to input. Any input will be received in the `on_input()` function. 2. Store a position vector `to` in `self` (the current script component) to keep track of where to do a raycast. 3. If we receive input (touch or mouse movement) we update the position to where we should cast the ray. 4. Perform a raycast from the current game object position to where the mouse/touch is. The raycast is configured to only hit collision objects belonging to the `stone` group. The result will be stored in `result` or `nil` if no hit. 5. The raycast hit something! Draw a line (using the helper function at the top of the script) from the current game object position to where the raycast hit. 6. The raycast missed! Draw a line (using the helper function at the top of the script) from the current game object position to where the mouse/touch was. --]] ``` # Trigger {#examples:physics:trigger} This example shows how a physics trigger is used to trigger an event. In this case the bunny sprite is disabled and enabled. [Project files](https://github.com/defold/examples/tree/master/physics/trigger) The setup consists of two game objects. trigger : The invisible trigger. Contains: - A *Collision object* component. The *Type* is set to `TRIGGER`. A box *Shape* is added to the components. bunny : The bunny. Contains: - A *Sprite* component with the bunny image. - A *Collision object* component. It has *Type* set to `DYNAMIC`. A sphere *Shape* matching the sprite image is added to the components. - A *Script* component that animates the bunny's position and reacts to physics messages when interacting with the trigger. ## Scripts ### bunny.script ```lua function init(self) local pos = go.get_position() -- <1> go.animate(".", "position.x", go.PLAYBACK_LOOP_PINGPONG, pos.x + 600, go.EASING_INOUTSINE, 6) end function on_message(self, message_id, message, sender) if message_id == hash("trigger_response") then -- <2> if message.enter then -- <3> msg.post("#sprite", "disable") -- <4> else msg.post("#sprite", "enable") -- <5> end end end --[[ 1. Get the current position, then animate the position's x component looping in a ping-pong manner against an offset of 600. 2. The physics engine has detected that this game object contains collision object components that have collided with a trigger. 3. The `message` data table contains a field `enter` that is set to `true` when the trigger event signals that the trigger shape was entered. On exiting the trigger, this field is `false`. 4. Disable the sprite when the trigger is entered 5. Enable the sprite again on exit. --]] ``` # Camera {#examples:render:camera} This example shows how to use a camera component and have it follow a game object. Click to toggle between following the game object and staying stationary. [Project files](https://github.com/defold/examples/tree/master/render/camera) The setup consists of one `bee` game object that the camera can follow and one `camera` game object containing the camera component. The camera component will when active send view and projection updates to the render script. bee : The bee. Contains: - A *Sprite* component with the bee image. - A script that tells the camera whether it should follow the game object or not. camera : The camera. Contains: - A *Camera* component. The camera component has Orthographic Projection enabled. - A script that controls the camera component. ## Scripts ### bee.script ```lua function init(self) msg.post(".", "acquire_input_focus") go.animate(".", "position.x", go.PLAYBACK_LOOP_PINGPONG, 2000, go.EASING_INOUTQUAD, 10) -- <1> msg.post("camera", "follow") -- <2> self.follow = true -- <3> end function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed then -- <4> self.follow = not self.follow if self.follow then msg.post("camera", "follow") else msg.post("camera", "unfollow") end end end --[[ 1. Move this game object back and forth across the scene. 2. Send a message to the camera game object telling it to follow this game object. 3. Keep track of if the camera is following this game object or not. 4. Toggle between following and not following the game object when the left mouse button is clicked or the screen is touched. --]] ``` ### camera.script ```lua function on_message(self, message_id, message, sender) if message_id == hash("follow") then -- <1> go.set_parent(".", sender) -- <2> elseif message_id == hash("unfollow") then -- <3> go.set_parent("camera", nil, true) end end --[[ 1. Start following the game object that sent the `follow` message. 2. This is done by parenting the camera component to the game object that sent the message. 3. Stop following any game object. This is done removing the parent game object while maintaining the current world transform. --]] ``` # Orbit Camera {#examples:render:orbit_camera} This example demonstrates how to create script to control a 3D camera with the mouse. Scroll wheel is used to zoom in and out. [Project files](https://github.com/defold/examples/tree/master/render/orbit_camera) In this example, we create a script to control a 3D camera using the mouse and mouse scroll wheel. We added two objects to the collection: a camera (`/camera`) and an object (`/crate`) that we will explore. In the `camera` object, we added the `orbit_camera.script` - the script that controls the camera. The properties defined in the script are: - `zoom`: the initial zoom level. - `zoom_speed`: the speed of the zoom. - `rotation_speed`: the speed of the rotation. - `offset`: the offset of the camera from the origin. Use it to move the camera away from the origin. During `init`, the script sets up the camera projection, acquires input focus, and establishes starting values for yaw, pitch, and zoom. In the `update` loop, the script smoothly interpolates camera rotation and zoom (note: `vmath.lerp` is used and it doesn't depend on the delta time, so the camera will move at different speed on different devices), calculates the camera's rotation and position based on current yaw, pitch, and zoom values, and then updates the camera's position and rotation accordingly. This creates a fluid, responsive camera movement! The function `on_input` handles user input to control the camera. As the user moves the mouse or touches the screen, the script adjusts the yaw and pitch values, allowing the camera to rotate around its focal point. Additionally, it responds to mouse wheel input, adjusting the zoom level to move the camera closer to or further from the center point. The model used in this example is from Kenney's [Prototype Pack](https://kenney.nl/assets/prototype-kit), licensed under CC0. ## Scripts ### orbit_camera.script ```lua -- The initial zoom level go.property("zoom", 3) -- The speed of the zoom go.property("zoom_speed", 0.1) -- The speed of the rotation go.property("rotation_speed", 0.5) -- The offset of the camera from the origin go.property("offset", vmath.vector3(0, 0, 0)) function init(self) -- Acquire input focus to receive input events msg.post(".", "acquire_input_focus") -- Initialize start values self.yaw = go.get(".", "euler.y") self.pitch = go.get(".", "euler.x") self.zoom_offset = 0 self.current_yaw = self.yaw self.current_pitch = self.pitch self.current_zoom = self.zoom_offset end function update(self, dt) -- Animate camera rotation and zoom self.current_yaw = vmath.lerp(0.15, self.current_yaw, self.yaw) self.current_pitch = vmath.lerp(0.15, self.current_pitch, self.pitch) self.current_zoom = vmath.lerp(0.15, self.current_zoom, self.zoom_offset) -- Calculate rotation and position local camera_yaw = vmath.quat_rotation_y(math.rad(self.current_yaw)) local camera_pitch = vmath.quat_rotation_x(math.rad(self.current_pitch)) local camera_rotation = camera_yaw * camera_pitch local camera_position = self.offset + vmath.rotate(camera_rotation, vmath.vector3(0, 0, self.zoom + self.current_zoom)) -- Set camera position and rotation go.set_position(camera_position) go.set_rotation(camera_rotation) end function on_input(self, action_id, action) if action_id == hash("touch") and not action.pressed then self.yaw = self.yaw - action.dx * self.rotation_speed self.pitch = self.pitch + action.dy * self.rotation_speed elseif action_id == hash("mouse_wheel_up") then self.zoom_offset = self.zoom_offset - self.zoom * self.zoom_speed elseif action_id == hash("mouse_wheel_down") then self.zoom_offset = self.zoom_offset + self.zoom * self.zoom_speed end end ``` # Orthographic Zoom {#examples:render:orthographic_zoom} This example shows how to zoom an orthographic camera in and out by changing Orthographic Zoom while the camera is in Fixed mode. [Project files](https://github.com/defold/examples/tree/master/render/orthographic_zoom) This example shows the recommended setup for gameplay zoom with an orthographic camera: keep the camera component in orthographic `Fixed` mode, then change `orthographic_zoom` from script. ## Setup The setup consists of three parts: - `camera` - game object containing the `camera` component, the `zoom.script`, and a `label` that displays the current zoom value. The `camera` component has `Orthographic Projection` enabled and `Orthographic Zoom Mode` set to `Fixed` with `Orthographic Zoom` set to `1.0` initially. - `tilemap`- a simple level tilemap that makes the zoom effect easy to see as you move between a closer and wider view. - `gui` - a GUI scene with a short instruction label describing the available controls. ## How it works * Scrolling the mouse wheel changes the camera zoom in small fixed steps. * Clicking or touching and moving up and down changes the zoom continuously based on the pointer delta. * The script clamps the zoom between minimum and maximum values before writing it back to the camera component, so the example stays within a useful range. Because the camera is in orthographic `Fixed` mode, the zoom behavior is controlled directly by the `orthographic_zoom` value instead of being recalculated by another orthographic mode. ## Credits This project uses the following free art assets: - Pixel Art Top Down Basic tilesets by Cainos: [https://cainos.itch.io/pixel-art-top-down-basic](https://cainos.itch.io/pixel-art-top-down-basic) ## Scripts ### zoom.script ```lua -- Local constants to define maximum and minimum zoom: local MIN_ZOOM = 0.75 local MAX_ZOOM = 3.0 -- Local constants to define how fast zooming is on input: local SCROLL_ZOOM_STEP = 0.1 local DRAG_ZOOM_SCALE = 0.01 -- Helper function to update the label with information on current zoom value. local function update_zoom_label(zoom) label.set_text("#zoom_label", string.format("Orthographic Zoom: %.2f", zoom)) end -- Helper function to clamp the zoom between minimum and maximum values. local function clamp_zoom(zoom) return math.min(MAX_ZOOM, math.max(MIN_ZOOM, zoom)) end -- Helper function to set the new clamped zoom on the camera component and update label. local function set_zoom(self, zoom) self.zoom = clamp_zoom(zoom) go.set("#camera", "orthographic_zoom", self.zoom) update_zoom_label(self.zoom) end function init(self) -- Acquire input focus for the example: msg.post(".", "acquire_input_focus") -- You can set manually the orthographic mode to fixed too -- (optional, as we set it in the component already): camera.set_orthographic_mode("#camera", camera.ORTHO_MODE_FIXED) -- Get the current zoom of the camera component: self.zoom = go.get("#camera", "orthographic_zoom") -- Update the information about zoom on the label: update_zoom_label(self.zoom) end function on_input(self, action_id, action) -- Handle input on mouse scroll and touch/click: if action_id == hash("mouse_wheel_up") then -- Increasing zoom makes the orthographic camera zoom in. set_zoom(self, self.zoom + SCROLL_ZOOM_STEP) elseif action_id == hash("mouse_wheel_down") then -- Decreasing zoom makes the orthographic camera zoom out. set_zoom(self, self.zoom - SCROLL_ZOOM_STEP) elseif action_id == hash("touch") and not action.pressed and not action.released then -- While dragging, use the vertical pointer delta for continuous zoom control. -- Positive `action.dy` means the pointer moved up on screen. go.cancel_animations("#camera", "orthographic_zoom") set_zoom(self, self.zoom + action.dy * DRAG_ZOOM_SCALE) end end ``` # Post-processing {#examples:render:post_processing} This example shows how to apply a post-processing effect by drawing to a render target and then to a fullscreen quad using a post processing shader. [Project files](https://github.com/defold/examples/tree/master/render/post_processing) The basic principle of a full screen post processing effect is to first draw the entire game to a render target, then draw this render target to a full screen quad using a post processing shader to apply some kind of effect. This example shows a color invert effect and a CRT scanline effect. The setup in this example consists of a custom render script and a game object containing a model component with a fullscreen quad (ie rectangle). The model uses a material with a render predicate/tag named `postprocess`. The material uses a basic shader program in `invert.fp` to invert the color of anything drawn with the material. The render script is a copy of the default render script with added code to create a fullscreen render target. The render target has a color and depth buffer, and it will be resized if the screen resolution changes: ```lua local function create_postprocess_rt(self, width, height) local color_params = { format = graphics.TEXTURE_FORMAT_RGBA, width = width, height = height, min_filter = render.FILTER_LINEAR, mag_filter = render.FILTER_LINEAR, u_wrap = render.WRAP_CLAMP_TO_EDGE, v_wrap = render.WRAP_CLAMP_TO_EDGE } local depth_params = { format = graphics.TEXTURE_FORMAT_DEPTH, width = width, height = height, } self.postprocess_rt = render.render_target("postprocess_rt", { [render.BUFFER_COLOR_BIT] = color_params, [render.BUFFER_DEPTH_BIT] = depth_params } ) self.postprocess_rt_width = width self.postprocess_rt_height = height end local function update_postprocess_rt(self) local w = render.get_window_width() local h = render.get_window_height() -- keep render target if size is the same if self.postprocess_rt_width == w and self.postprocess_rt_height == h then return end render.delete_render_target(self.postprocess_rt) create_postprocess_rt(self, w, h) end function init(self) -- create the postprocess predicate and all of the default predicates self.predicates = create_predicates("postprocess", "tile", "gui", "particle", "model", "debug_text") create_postprocess_rt(self, render.get_window_width(), render.get_window_height()) end function update(self) update_postprocess_rt(self) end ``` The render script is additionally modified so that all content is drawn to the render target instead of directly to the screen. In a separate step at the end, the render target is used as a texture and drawn to the fullscreen quad with the `postprocess` predicate using the post processing shader assigned to the model quad: ```lua function update(self) update_postprocess_rt(self) -- enable postprecssing render target -- subsequent draw operations will be done to the render target -- render.set_render_target(self.postprocess_rt) -- note: some render code removed from this snippet to make it readable render.draw(predicates.model, draw_options_world) render.draw(predicates.tile, draw_options_world) render.draw(predicates.particle, draw_options_world) render.draw(predicates.gui, camera_gui.options) render.draw(predicates.debug_text, camera_gui.options) -- revert to the default render target -- render.set_render_target(render.RENDER_TARGET_DEFAULT) -- render post processing render target to quad with predicate 'postprocess' -- render.set_view(vmath.matrix4()) render.set_projection(vmath.matrix4()) render.enable_texture(0, self.postprocess_rt, render.BUFFER_COLOR_BIT) render.draw(predicates.postprocess) render.disable_texture(0) end ``` Additionally the example shows in `postprocess.script` how to change material using material resource properties at runtime. ## Scripts ### postprocess.script ```lua go.property("invert", resource.material("/example/materials/invert.material")) go.property("passthrough", resource.material("/example/materials/passthrough.material")) go.property("scanlines", resource.material("/example/materials/scanlines.material")) function init(self) msg.post(".", "acquire_input_focus") go.set("#quad", "material", self.invert) end function on_input(self, action_id, action) if action_id == hash("key_1") then go.set("#quad", "material", self.invert) elseif action_id == hash("key_2") then go.set("#quad", "material", self.scanlines) local w, h = window.get_size() go.set("#quad", "resolution", vmath.vector4(w, h, 0, 0)) elseif action_id == hash("key_3") then go.set("#quad", "material", self.passthrough) end end ``` ### invert.fp ```glsl #version 140 in mediump vec2 var_texcoord0; out vec4 out_fragColor; uniform mediump sampler2D tex0; void main() { vec4 color = texture(tex0, var_texcoord0.xy); color.r = 1.0 - color.r; color.g = 1.0 - color.g; color.b = 1.0 - color.b; out_fragColor = vec4(color.rgb,1.0); } ``` ### invert.vp ```glsl #version 140 in highp vec4 position; in mediump vec2 texcoord0; out mediump vec2 var_texcoord0; uniform vs_uniforms { highp mat4 view_proj; }; void main() { gl_Position = view_proj * vec4(position.xyz, 1.0); var_texcoord0 = texcoord0; } ``` # Screen to World {#examples:render:screen_to_world} This example shows how to convert from screen to world coordinates while using a camera. [Project files](https://github.com/defold/examples/tree/master/render/screen_to_world) The `bee.script` uses the `camera.screen_to_world()` function to convert from screen space coordinates to world coordinates using the view and projection of a camera component. ## Scripts ### bee.script ```lua function init(self) -- send input events to this script msg.post(".", "acquire_input_focus") end function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed then -- convert mouse/touch screen position to world position local screen = vmath.vector3(action.screen_x, action.screen_y, 0) local world = camera.screen_to_world(screen, "#camera") -- alternative using camera.screen_xy_to_world(x, y, camera) -- local world = camera.screen_xy_to_world(action.screen_x, action.screen_y, v) -- animate bee to new world position go.animate(".", "position", go.PLAYBACK_ONCE_FORWARD, world, go.EASING_LINEAR, 0.5, 0) end end ``` # World to Screen {#examples:render:world_to_screen} This example demonstrates how to convert 3D world coordinates to 2D screen coordinates using camera transformations. [Project files](https://github.com/defold/examples/tree/master/render/world_to_screen) This example shows how to convert world positions to screen coordinates for UI positioning. It features: * Use of the built-in `camera.world_to_screen()` API to transform 3D world positions to 2D screen coordinates. * A reference Lua `world_to_screen()` implementation (below) kept as an example to help understand how the conversion works internally. * A ghost character that rotates around a crypt in 3D space while floating up and down. * A player name label in the GUI that follows the character's world position by converting it to screen coordinates. * Demonstrates practical use of world-to-screen conversion for positioning UI elements relative to 3D objects. Note: The reference Lua version does not preserve depth information and always returns `z = 0` to keep the code simpler. ```lua --- Converts a world position to screen coordinates. -- This function transforms a 3D world position to 2D screen coordinates using the camera's -- view and projection matrices. The resulting coordinates are in screen space where (0,0) -- is the bottom-left corner of the screen. -- -- @param world_position vector3 The world position to convert. -- @param camera_url url|string The camera component URL to use for the transformation. -- @return number screen_x The X coordinate in screen space. -- @return number screen_y The Y coordinate in screen space. -- @return number screen_z Always returns 0 (depth information is not preserved). local function world_to_screen(world_position, camera_url) local proj = camera.get_projection(camera_url) local view = camera.get_view(camera_url) local view_proj = proj * view local scr_coord = view_proj * vmath.vector4(world_position.x, world_position.y, world_position.z, 1) local w, h = window.get_size() scr_coord.x = (scr_coord.x / scr_coord.w + 1) * 0.5 * w scr_coord.y = (scr_coord.y / scr_coord.w + 1) * 0.5 * h return vmath.vector3(scr_coord.x, scr_coord.y, 0) end ``` ## Scripts ### player.script ```lua go.property("camera_url", msg.url("/camera#camera")) -- URL of the camera component go.property("hud_url", msg.url("/ui#hud")) go.property("angle", -45) -- we use this property to animate the rotation of the player around the center of the scene function init(self) -- Get the IDs of the player view and UI objects self.player_view_id = go.get_id("player_view") self.player_ui_id = go.get_id("player_ui") -- Animate vertical position of the body local new_pos_y = go.get(self.player_view_id, "position.y") + 0.2 go.animate(self.player_view_id, "position.y", go.PLAYBACK_LOOP_PINGPONG, new_pos_y, go.EASING_INOUTSINE, 2) -- Get the base position self.base_pos = go.get_position() -- Animate the angle to rotate the player around the center of the scene go.animate("#", "angle", go.PLAYBACK_LOOP_FORWARD, -3600 + self.angle, go.EASING_LINEAR, 200) end function final(self) end function update(self, dt) -- Update the position of the player based on the angle and the base position local radius = self.base_pos.z go.set_position(vmath.vector3(radius * math.sin(math.rad(self.angle)), self.base_pos.y, radius * math.cos(math.rad(self.angle)))) -- Update the rotation of the player based on the angle go.set(".", "euler.y", self.angle + 90) -- Update the world transform of the player UI object and convert the world position to screen coordinates go.update_world_transform(self.player_ui_id) local world_pos = go.get_world_position(self.player_ui_id) local screen_pos = camera.world_to_screen(world_pos, self.camera_url) -- Send the screen position to the HUD script msg.post(self.hud_url, "update_data", { screen_position = screen_pos }) end ``` # Create atlas {#examples:resource:create_atlas} This example shows how to create an atlas with two images and use it on a sprite and in a gui [Project files](https://github.com/defold/examples/tree/master/resource/create_atlas) The example creates a texture and an atlas with two images and uses the two images on a sprite and a gui box node. ## Scripts ### create_atlas.script ```lua local function create_texture(width, height) -- create a new rgba texture local create_texture_params = { width = width, height = height, type = resource.TEXTURE_TYPE_2D, format = resource.TEXTURE_FORMAT_RGBA, } local my_texture_id = resource.create_texture("/my_custom_texture.texturec", create_texture_params) -- create a buffer with pixel data local buf = buffer.create(width * height, { { name=hash("rgba"), type=buffer.VALUE_TYPE_UINT8, count=4 } } ) local stream = buffer.get_stream(buf, hash("rgba")) local half_width = width / 2 for y=1, height do for x=1, width do local index = (y-1) * width * 4 + (x-1) * 4 + 1 stream[index + 0] = x > half_width and 0xFF or 0x00 stream[index + 1] = x > half_width and 0x00 or 0xFF stream[index + 2] = x > half_width and 0x00 or 0x00 stream[index + 3] = 0xFF end end -- set the pixels on the texture local set_texture_params = { width=width, height=height, x=0, y=0, type=resource.TEXTURE_TYPE_2D, format=resource.TEXTURE_FORMAT_RGBA, num_mip_maps=1 } resource.set_texture(my_texture_id, set_texture_params, buf) return my_texture_id end local function create_atlas(texture_id, width, height) local params = { texture = texture_id, animations = { { id = "my_animation_left", width = width / 2, height = height, frame_start = 1, frame_end = 2, }, { id = "my_animation_right", width = width / 2, height = height, frame_start = 2, frame_end = 3, } }, geometries = { { width = width / 2, height = height, pivot_x = 0.5, pivot_y = 0.5, vertices = { 0, height, 0, 0, width / 2, 0, width / 2, height }, uvs = { 0, height, 0, 0, width / 2, 0, width / 2, height }, indices = {0,1,2,0,2,3} }, { width = width / 2, height = height, pivot_x = 0.5, pivot_y = 0.5, vertices = { 0, height, 0, 0, width / 2, 0, width / 2, height }, uvs = { width / 2, height, width / 2, 0, width, 0, width, height }, indices = {0,1,2,0,2,3} } } } local my_atlas_id = resource.create_atlas("/my_atlas.texturesetc", params) return my_atlas_id end function init(self) local width = 128 local height = 128 local my_texture_id = create_texture(width, height) local my_atlas_id = create_atlas(my_texture_id, width, height) -- set the new atlas on the sprite and show one image go.set("#sprite", "image", my_atlas_id) sprite.play_flipbook("#sprite", "my_animation_left") -- set the new atlas on the gui component and use on a node from the gui script go.set("gui#gui", "textures", my_atlas_id, { key = "my_atlas" }) msg.post("gui#gui", "use_atlas", { texture = "my_atlas", animation = "my_animation_right" }) end ``` ### create_atlas.gui_script ```lua function on_message(self, message_id, message, sender) if message_id == hash("use_atlas") then local box = gui.get_node("box") gui.set_texture(box, message.texture) gui.play_flipbook(box, message.animation) end end ``` # Modify atlas {#examples:resource:modify_atlas} This example shows how to replace an image in an atlas [Project files](https://github.com/defold/examples/tree/master/resource/modify_atlas) The example loads an image bundled as a custom resource (bundled in the game archive) and uses it to replace the first image of an atlas. See code comments for implementation details. ## Scripts ### modify_atlas.script ```lua -- load image from custom resources -- read pixels and write them to a buffer local function create_buffer_from_image(filename) local png = assert(sys.load_resource(filename)) local loaded_image = image.load(png) local width = loaded_image.width local height = loaded_image.height local pixels = loaded_image.buffer local buffer_declaration = { { name = hash("rgba"), type = buffer.VALUE_TYPE_UINT8, count = 4 } } local pixel_buffer = buffer.create(width * height, buffer_declaration) local pixel_stream = buffer.get_stream(pixel_buffer, hash("rgba")) for y = 1, height do for x = 1, width do -- flip image local pixels_index = ((height - y) * width * 4) + ((x - 1) * 4) + 1 local r = pixels:byte(pixels_index + 0) local g = pixels:byte(pixels_index + 1) local b = pixels:byte(pixels_index + 2) local a = pixels:byte(pixels_index + 3) -- write to buffer stream local stream_index = ((y - 1) * width * 4) + ((x - 1) * 4) + 1 pixel_stream[stream_index + 0] = r pixel_stream[stream_index + 1] = g pixel_stream[stream_index + 2] = b pixel_stream[stream_index + 3] = a end end return pixel_buffer, width, height end local function replace_atlas_image() -- get table with information about an atlas local atlas = resource.get_atlas("/example/modify_atlas.a.texturesetc") -- get table with information about the textured used by the atlas local texture = resource.get_texture_info(atlas.texture) pprint(atlas) pprint(texture) -- load an image as a Defold buffer local pixel_buffer, width, height = create_buffer_from_image("/example/resources/shipYellow_manned.png") -- get the UV coordinates of the first image in the atlas local first_uvs = atlas.geometries[1].uvs -- this offset should not be necessary but it seems like there is an issue with the -- UVs in Defold 1.5.0 local x = first_uvs[1] - 0 local y = first_uvs[2] - 6 print(x, y) print(width, height) -- create a table with texture update information -- we want to update only a sub region of the atlas starting at a -- certain position and with a certain size local texture_info = { type = resource.TEXTURE_TYPE_2D, width = width, height = height, format = resource.TEXTURE_FORMAT_RGBA, x = x, y = y, compression_type = resource.COMPRESSION_TYPE_DEFAULT, num_mip_maps = texture.mipmaps, } -- update the atlas texture with the pixels from the provided buffer resource.set_texture(atlas.texture, texture_info, pixel_buffer) end function init(self) msg.post(".", "acquire_input_focus") end function on_input(self, action_id, action) if action_id == hash("mouse_button_left") and action.pressed then replace_atlas_image() end end ``` # Fade In-Out {#examples:sound:fade_in_out} This example shows how to make Fade-In and fade Fade-Out music. [Project files](https://github.com/defold/examples/tree/master/sound/fade_in_out) ## Scripts ### fade_in_out.script ```lua local TIME = 2 -- <1> local DELAY = 1 -- <2> function init(self) sound.play("#music", { gain = 1.0 }) -- <3> msg.post("#", "fade_in_out") -- <4> end function on_message(self, message_id, message, sender) if message_id == hash("fade_in_out") then go.animate("#music", "gain", go.PLAYBACK_LOOP_PINGPONG, 0, go.EASING_LINEAR, TIME, DELAY) -- <5> end end --[[ 1. Create TIME constant - duration of the fade-in and fade-out effect. 2. Create DELAY constant - pause before the start of the fade-in and fade-out effect. 3. Tell the component "#music" to start playing its sound with a gain of 1.0 4. Send a "fade_in_out" message to the script telling it to start fading the music in and out 5. Animate the "gain" property of the sound component back and forth between 0 and the current value (1.0) --]] ``` # Get and set sound {#examples:sound:get_set_sound} This example shows how to change which sound a sound component plays [Project files](https://github.com/defold/examples/tree/master/sound/get_set_sound) This example shows how to change which sound a sound component plays. Additional sounds are stored as individual .ogg files in the `sounds` folder and included in the build as [Custom Resources](https://defold.com/manuals/file-access/#custom-resources): The example consists of a single collection with a game object containing a Sound component, a Sprite component for visuals and a Script to control the logic: Sound effects and space ship by [Kenney](https://www.kenney.nl) ## Scripts ### get_set_sound.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- animate the spaceship up and down "for dramatic effect" go.animate(".", "position.y", go.PLAYBACK_LOOP_PINGPONG, go.get_position().y + 20, go.EASING_INOUTQUAD, 1) -- play the engine sound sound.play("#enginesound") end function on_input(self, action_id, action) if action_id == hash("mouse_button_left") and action.pressed then -- a list of sounds to chose between local sounds = { "/sounds/spaceEngine_001.ogg", "/sounds/spaceEngine_002.ogg", "/sounds/spaceEngine_003.ogg", } -- pick one at random local random_sound = sounds[math.random(1, #sounds)] -- load the new sound -- stop the currently playing sound -- set the sound on the sound component -- play it again local engine3 = sys.load_resource(random_sound) sound.stop("#enginesound") resource.set_sound(go.get("#enginesound", "sound"), engine3) sound.play("#enginesound") end end ``` # Music {#examples:sound:music} This example shows how to play a piece of music, stored as an .OGG file, with a sound component. The sound component is set to "looping" causing the music to never, ever stop. [Project files](https://github.com/defold/examples/tree/master/sound/music) ## Scripts ### music.script ```lua function init(self) sound.play("#music", { gain = 1.0, pan = 0 }) -- <1> end --[[ 1. Tell the component "#music" to start playing its sound. The sound will be played with gain 1.0 (max volume) and pan 0.0 (equal left-right channel) --]] ``` # Panning {#examples:sound:panning} This example demonstrates how to pan a sound effect according to a GO's(game object) position on the screen. [Project files](https://github.com/defold/examples/tree/master/sound/panning) Overview : A coin bounces around the screen and on collision detection we get the coins x position then normalize that value for use in the sound components pan property. As the API states "The pan on the sound-component. The valid range is from -1.0 to 1.0, representing -45 degrees left, to +45 degrees right." we can use this information along with our x value from our coin object and normalize it into the correct range. The setup consists of a coin game object, three stone objects and walls for collision. Coin : contains: - A *Sound* component. - A *Collision* component. With *Type* set to `DYNAMIC` and a Sphere *Shape*. - A script used to set initial coin movement then set pan value and play a sound on collision. - A sprite component with default animation set as coin Stones : contains: - A *Collision* component set to `STATIC` and 1 box *Shape* to match the sprite image. Walls : contains: - A *Collision* component set to `STATIC` and 4 box *Shapes* that make up the walls along the bounds of the game screen. ## Scripts ### pan.script ```lua local position_min = 0 -- <1> local position_max = sys.get_config_int("display.width") -- <2> local function normalize_position(x_position) -- <3> local average = (position_min + position_max) / 2 local range = (position_max - position_min) / 1.8 local result = (x_position - average) / range return result end function on_message(self, message_id, message, sender) -- <4> if message_id == hash("collision_response") then local coin_pos = normalize_position(go.get_position().x) sound.play("#coin", { gain = 0.6, pan = coin_pos } ) end end --[[ 1. - Local variable to represent the minimum x position value. 2. - Local variable to represent the maximum x position value. sys.get_config_int("display.width") to get screen width used for maximum x position value. 3. - This function uses the screen x position min & max local variables that is set at the top of the script to get an average and range then pass in the coin objects x position into result to get a normalized value and the function returns that value. note: in range if we divide by 2.0 we would get range -1.0 to 1.0 full 45 degree pan at min/max positions, instead use 1.8 to get around a 40 deg pan that way we always get a little bit of sound in both left and right channel outputs no matter the min/max position. 4. - When a collision_response is received we pass in the coin objects x position into the normalize_position function and set the results to the local variable coin_pos. Then play a sound and pass in coin_pos into the sounds pan property. Now we have simple sound localization using the pan property. If you close your eyes, you should be able to gauge which direction the collisions are occurring.(as long as you are using stereo sound) --]] ``` # Bunnymark {#examples:sprite:bunnymark} This is a performance test for sprites [Project files](https://github.com/defold/examples/tree/master/sprite/bunnymark) The example spawns game objects and animates them using go.animate(). An alternative bunnymark test with more options can be found [here](https://github.com/britzl/defold-bunnymark). ## Scripts ### bunnymark.script ```lua local BUNNY_IMAGES = { hash("rabbitv3_batman"), hash("rabbitv3_bb8"), hash("rabbitv3"), hash("rabbitv3_ash"), hash("rabbitv3_frankenstein"), hash("rabbitv3_neo"), hash("rabbitv3_sonic"), hash("rabbitv3_spidey"), hash("rabbitv3_stormtrooper"), hash("rabbitv3_superman"), hash("rabbitv3_tron"), hash("rabbitv3_wolverine"), } local DISPLAY_WIDTH = sys.get_config_int("display.width") local DISPLAY_HEIGHT = sys.get_config_int("display.height") local SPAWN_COUNT = 1000 local function spawn(self, amount) for i=1,amount do local bunny = factory.create("#factory") if bunny then local img = BUNNY_IMAGES[math.random(1, #BUNNY_IMAGES)] sprite.play_flipbook(msg.url(nil, bunny, "sprite"), img) go.set_position(vmath.vector3(math.random(DISPLAY_WIDTH), DISPLAY_HEIGHT, 0), bunny) go.animate(bunny, "position.y", go.PLAYBACK_LOOP_PINGPONG, 40, go.EASING_INQUAD, 2, math.random()) self.bunnies = self.bunnies + 1 else print("Unable to create more bunnies") break end end end function init(self) msg.post(".", "acquire_input_focus") self.frames = {} self.bunnies = 0 spawn(self, SPAWN_COUNT) end function update(self, dt) self.frames[#self.frames + 1] = socket.gettime() local fps = 0 if #self.frames == 61 then table.remove(self.frames, 1) fps = 1 / ((self.frames[#self.frames] - self.frames[1]) / (#self.frames - 1)) end label.set_text("#label", ("Bunnies: %d FPS: %.2f. Click to add more"):format(self.bunnies, fps)) end function on_input(self, action_id, action) if action_id == hash("touch") and action.released and action.y < 1030 then spawn(self, SPAWN_COUNT) end end ``` # Change sprite image {#examples:sprite:changeimage} This example shows how to change the image of a sprite [Project files](https://github.com/defold/examples/tree/master/sprite/changeimage) The example shows a game object with a sprite and a script with three script properties to reference different tilesource images. The script lets the user change which image to use on the sprite. It is also possible to use a script property to reference an atlas instead of a tilesource: ```lua go.property("hero", resource.atlas("/assets/hero.atlas")) function init(self) go.set("#sprite", "image", self.hero) end ``` ## Scripts ### changeimage.script ```lua -- create script properties with references to three different tile sources go.property("robot", resource.tile_source("/assets/robot.tilesource")) go.property("zombie", resource.tile_source("/assets/zombie.tilesource")) go.property("adventurer", resource.tile_source("/assets/adventurer.tilesource")) local function update_tilesource(image_id) -- set the sprite image property to the specified tilesource go.set("#sprite", "image", image_id) -- play the run animation sprite.play_flipbook("#sprite", "run") end function init(self) msg.post(".", "acquire_input_focus") update_tilesource(self.robot) end -- change sprite image when key 1, 2 and 3 are pressed function on_input(self, action_id, action) if action.pressed then if action_id == hash("key_1") then update_tilesource(self.robot) elseif action_id == hash("key_2") then update_tilesource(self.zombie) elseif action_id == hash("key_3") then update_tilesource(self.adventurer) end end end ``` # Flip {#examples:sprite:flip} This example demonstrates flipping a sprite animation vertically and horizontally. [Project files](https://github.com/defold/examples/tree/master/sprite/flip) Overview : [sprite.set_hflip](https://defold.com/ref/beta/sprite/#sprite.set_hflip:url-flip) & [sprite.set_vflip](https://defold.com/ref/beta/sprite/#sprite.set_vflip:url-flip) uses a boolean to set if a sprite animation should be flipped. The setup consists of 2 bee game object's, another game object for text labels and a single script. 2 Game Object's : containing: - A sprite with default animation set to bee 1 Game object : contains: - A script - 2 text labels Script : use: - Sets sprite flip and go.animation for bee game objects. ## Scripts ### flip.script ```lua local horizontal = "bee1" -- < 1 > local vertical = "bee2" local function bee_flip(go_id) -- < 2 > if go_id == horizontal then local bee_position = go.get_position(horizontal) if bee_position.x == 400 then sprite.set_hflip("bee1#sprite", false) go.animate(horizontal,"position.x",go.PLAYBACK_ONCE_FORWARD,120,go.EASING_INOUTCUBIC,3.5,0,function()bee_flip(horizontal)end) else sprite.set_hflip("bee1#sprite", true) go.animate(horizontal,"position.x",go.PLAYBACK_ONCE_FORWARD,400,go.EASING_INOUTCUBIC,3.5,0,function()bee_flip(horizontal)end) end else local bee_position = go.get_position(vertical) if bee_position.y == 520 then sprite.set_vflip("bee2#sprite", true) go.animate(vertical,"position.y",go.PLAYBACK_ONCE_FORWARD,200,go.EASING_INOUTCUBIC,3.5,0.6,function()bee_flip(vertical)end) else sprite.set_vflip("bee2#sprite", false) go.animate(vertical,"position.y",go.PLAYBACK_ONCE_FORWARD,520,go.EASING_INOUTCUBIC,3.5,0.6,function()bee_flip(vertical)end) end end end function init(self) -- < 3 > bee_flip(horizontal) bee_flip(vertical) end --[[ 1. 2 game object id's are set as local strings for horizontal and vertical examples. 2. bee_flip() function takes in the go's id then an if statement is used to determine go's position and sets horizontal or vertical flip to sprite accordingly. Then go.animate is used and a callback to bee_flip() occurs at the end of the animation. 3. In the initialize function we call bee_flip() for both horizontal and vertical bee game objects. --]] ``` # Multiple Sprite Samplers {#examples:sprite:samplers} This example shows how to sample from more than one image when drawing a sprite [Project files](https://github.com/defold/examples/tree/master/sprite/samplers) The example uses a sprite with a material with two samplers: The samplers are assigned to two atlases, `one.atlas` and `two.atlas`: Each atlas contains a Defold logo: Note the rename pattern in `two.atlas`. The rename pattern is required so that it is possible to sample from the same location in both atlases. The color data from the two samplers is mixed/interpolated in the fragment program to produce a final color. The amount of interpolation is controlled in the `mix_amount` fragment constant. The `mix_amount` is animated between 0.0 and 1.0 in the `multi_sample.script` ## Scripts ### multi_sample.script ```lua function init(self) go.animate("logo#sprite", "mix_amount.x", go.PLAYBACK_LOOP_PINGPONG, 1.0, go.EASING_INOUTQUAD, 2) end ``` ### multi_sample_sprite.fp ```glsl varying mediump vec2 var_texcoord0; uniform lowp sampler2D texture1_sampler; uniform lowp sampler2D texture2_sampler; uniform lowp vec4 tint; uniform lowp vec4 mix_amount; void main() { // Pre-multiply alpha since all runtime textures already are lowp vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w); // sample from both textures lowp vec4 color1 = texture2D(texture1_sampler, var_texcoord0.xy); lowp vec4 color2 = texture2D(texture2_sampler, var_texcoord0.xy); // mix (interpolate) the colors by the mix_amount lowp vec4 colormix = mix(color1, color2, mix_amount.x); // apply tint gl_FragColor = colormix * tint_pm; } ``` # Sprite cursor {#examples:sprite:cursor} This example shows how to use the sprite animation cursor and frame count to manually select a specific frame [Project files](https://github.com/defold/examples/tree/master/sprite/cursor) The example contains a sprite with a tilesource animation of a walking robot. The animation consists of 8 frames: The example also contains a script and some visual controls that can be used to step through or automatically play the tilesource animation using the animation cursor: ## Scripts ### cursor.script ```lua -- step animation forward or backwards 'amount' number of frames local function step(self, amount) -- frame_count is the number of frames in the current animationm local frame_count = go.get("#sprite", "frame_count") -- cursor is the normalized (0.0 to 1.0) animation cursor local cursor = go.get("#sprite", "cursor") -- normalized length of a frame in the current animation local frame_length = 1 / frame_count -- move the cursor amount number of frames cursor = cursor + (frame_length * amount) -- wrap animation if advancing beyond the first or last frame if cursor < 0 then cursor = cursor + 1 elseif cursor >= 1 then cursor = cursor - 1 end -- set new sprite cursor position go.set("#sprite", "cursor", cursor) -- calculate the current animation frame and show on a label local current_frame = 1 + math.floor(cursor * frame_count) label.set_text("#frame", ("%d / %d"):format(current_frame, frame_count)) end -- stop automatic animation playback local function stop(self) -- only try to stop if there is an active timer if self.playback_timer then -- visually update the start/stop sprite to show the 'start image sprite.play_flipbook("controls#playstop", "start") -- cancel the animation timer timer.cancel(self.playback_timer) self.playback_timer = nil end end -- start automatic animation playback using a timer to advance the animation -- one frame at a time local function start(self) -- visually update the start/stop sprite to show the 'stop' image sprite.play_flipbook("controls#playstop", "stop") -- start a timer to advance the animation roughly every 0.15 seconds self.playback_timer = timer.delay(0.15, true, function() step(self, 1) end) end function init(self) msg.post(".", "acquire_input_focus") self.playback_timer = nil end function on_input(self, action_id, action) if action.pressed then -- key left or mouse click on left part of screen -- step animation one frame backwards if action_id == hash("key_left") or action_id == hash("mouse_button_left") and action.x < 240 then stop(self) step(self, -1) return end -- key right or mouse click on right part of the screen -- step animation one frame forward if action_id == hash("key_right") or action_id == hash("mouse_button_left") and action.x > 480 then stop(self) step(self, 1) return end -- key space or mouse click in central part of the screen -- start or stop animation playback if action_id == hash("key_space") or action_id == hash("mouse_button_left") and action.x > 240 and action.x < 480 then if self.playback_timer then stop(self) else start(self) end end end end ``` # Sprite size {#examples:sprite:size} This example shows how to get the size of a sprite at run-time [Project files](https://github.com/defold/examples/tree/master/sprite/size) The example uses two game objects, each with a sprite component and a label (to show the size). One of game objects contains the script that reads the size and shows it on the labels: ## Scripts ### size.script ```lua function init(self) local rectangle_size = go.get("#stone", "size") -- <1> local square_size = go.get("square#stone", "size") -- <2> label.set_text("#info", "" .. rectangle_size.x .. "x" .. rectangle_size.y) -- <3> label.set_text("square#info", "" .. square_size.x .. "x" .. square_size.y) -- <4> end --[[ 1. Read the size of the sprite with id `stone` on the same game object as this script (the game object with id `rectangle`). 2. Read the size of the sprite with id `stone` on the game object with id `square`. 3. Set the text of the label with id `info` on the same game object as this script (the game object with id `rectangle`). 4. Set the text of the label with id `info` on the game object with id `square`. --]] ``` # Sprite tint {#examples:sprite:tint} This example shows how tint a sprite at run-time [Project files](https://github.com/defold/examples/tree/master/sprite/tint) The example uses a script to tint (color) sprites in a couple of different ways. The tint is a fragment constant on the sprite material and it is used in the sprite.fp fragment shader program to modify the color sampled from the texture. It is important to keep in mind that each tinted sprite generates a new draw call since a modified tint value will break the built in draw call batching in Defold. ## Scripts ### tint.script ```lua function init(self) go.set("logo1#sprite", "tint", vmath.vector4(1, 0, 0, 1)) -- <1> go.set("logo2#sprite", "tint.x", 0) -- <2> go.set("logo3#sprite", "tint.w", 0.3) -- <3> go.animate("logo4#sprite", "tint", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(0, 0.5, 0.8, 1), go.EASING_INOUTQUAD, 2) -- <4> go.animate("logo5#sprite", "tint.w", go.PLAYBACK_LOOP_PINGPONG, 0, go.EASING_INOUTQUAD, 3) -- <4> end --[[ 1. x,y,z,w -> r,g,b,a. Keep red and alpha. Remove green and blue. 2. x = red. Remove the red color component completely 3. w = alpha. Make the sprite semi-transparent 4. The tint property can be animated, either as a whole or each individual value --]] ``` # Texture scrolling {#examples:sprite:texture_scrolling} This example shows how scroll the texture in the runtime using Texture Transform 2D Vertex Attribute, without using the sprite in the world space. [Project files](https://github.com/defold/examples/tree/master/sprite/texture_scrolling) # Texture scrolling This example shows how to achieve **scrolling textures (UV scrolling)** in Defold without moving the sprite in world space. Instead, UVs are modified in the fragment shader. It works both with plain textures and with an **atlas**, and the scrolling is performed **inside the current atlas region**. Since Defold 1.12.3 a new semantic type for Attributes is available named **"Texture Transform 2D"**, and it is used in this example. Since Defold 1.12.3 also time is provided automatically to the shaders via Fragment Constant of type **"Time"**, and it is used in this example. ## Material Setup 1. Create a new material: `example/scrolling.material`, with these important things set: - **Vertex attribute** `translation` (vec2) - Vector Type: `Vec2` (for 2D) - This is the UV scroll vector - defining direction and speed, meaning: `translation = (vx, vy)` where positive `vx` scrolls towards +U, and positive `vy` scrolls towards +V. - **Fragment constant** `time` of type `Time` - A material constant filled automatically by Defold. - In this example the fragment shader uses `time.x` as “time in seconds”, which is enough for simple scrolling. - Tint is left as is, as it's based on the built-in Sprite material. ## Sprite setup In `example/texture_scrolling.collection`, there are 4 sprites that all use the `scrolling.material` and mainly differ by the Vertex Attribute for **translation**, to achieve different direction and speed: - `(0.1, 0.0)` – scroll to the right - `(0.1, -0.1)` – scroll diagonally (right + down) - `(-0.1, 0.1)` – scroll diagonally (left + up) - `(0.0, 0.1)` – scroll up Notice, that visually it looks like the texture is moving in the **opposite** direction, because we are scrolling to the given direction the sampled texture. To control per-sprite scroll speed/direction, **just change the `translation`** on that sprite in the editor (Vertex Attributes for Sprite components). ## Shaders overview - **Vertex shader** `example/scrolling.vp` - Transforms sprite vertices to clip space using `view_proj`. - Forwards `texcoord0`, `texture_transform_2d`, and `translation` to the fragment shader. - **Fragment shader** `example/scrolling.fp` - Derives the atlas tile origin (`atlas_pos`) and size (`atlas_size`) from `texture_transform_2d`. - Converts atlas UV into local tile UV (0..1). - Applies scrolling using `localUV += translation * time.x`. - Wraps inside the tile with `fract(localUV)` to keep sampling within the region. - Converts back to atlas UV and samples `texture_sampler`. ## Scripts ### scrolling.vp ```glsl #version 140 // Positions are in world space. in highp vec4 position; in mediump vec2 texcoord0; in mediump mat3 texture_transform_2d; in vec2 translation; out mediump vec2 var_texcoord0; out mediump mat3 var_texture_transform; out vec2 var_translation; uniform vs_uniforms { highp mat4 view_proj; }; void main() { gl_Position = view_proj * vec4(position.xyz, 1.0); var_texcoord0 = texcoord0; var_texture_transform = texture_transform_2d; var_translation = translation; } ``` ### scrolling.fp ```glsl #version 140 in mediump vec2 var_texcoord0; in mediump mat3 var_texture_transform; in vec2 var_translation; out vec4 out_fragColor; uniform mediump sampler2D texture_sampler; uniform fs_uniforms { mediump vec4 tint; vec4 time; }; void main() { // Pre-multiply alpha since all runtime textures already are. vec4 tint_pm = vec4(tint.xyz * tint.w, tint.w); // Region origin in atlas UV space. vec2 atlas_pos = var_texture_transform[2].xy; // Region size in atlas UV space. // The first two columns encode basis vectors; their lengths correspond to size. vec2 atlas_size = vec2( length(var_texture_transform[0].xy), length(var_texture_transform[1].xy) ); // Convert to local tile UV (0..1). vec2 localUV = (var_texcoord0 - atlas_pos) / atlas_size; // Scroll in local UV space. localUV += (var_translation.xy) * time.x; // Wrap inside tile. localUV = fract(localUV); // Convert back to atlas space. vec2 finalUV = atlas_pos + localUV * atlas_size; out_fragColor = texture(texture_sampler, finalUV) * tint_pm; out_fragColor.a = 1.0; } ``` # Get and set tiles {#examples:tilemap:get_set_tile} This example shows how to get and set tiles of a tilemap [Project files](https://github.com/defold/examples/tree/master/tilemap/get_set_tile) This example uses a tilemap and a script file to read mouse input to place tiles or read information about the tile the mouse is hovering. --- Tilemap graphics made by [Kenney](https://www.kenney.nl). ## Scripts ### get_set_tile.script ```lua local TILE_SIZE = 64 -- helper function check if a tile coordinate is within the bounds of the tilemap local function within_bounds(x, y) local bx, by, bw, bh = tilemap.get_bounds("#level") return x >= bx and y >= by and x < (bx + bw) and y < (by + bh) end function init(self) msg.post(".", "acquire_input_focus") end function on_input(self, action_id, action) local tile_x = math.ceil(action.x / TILE_SIZE) local tile_y = math.ceil(action.y / TILE_SIZE) if within_bounds(tile_x, tile_y) then -- click to place a flower if action_id == hash("touch") and action.pressed then tilemap.set_tile("#level", "layer1", tile_x, tile_y, 77) end -- show tile info local tile = tilemap.get_tile("#level", "layer1", tile_x, tile_y) local text = ("x: %d y: %d tile: %d"):format(tile_x, tile_y, tile) label.set_text("#label", text) else local text = ("x: %d y: %d out of bounds"):format(tile_x, tile_y) label.set_text("#label", text) end end ``` # Tilemap collisions {#examples:tilemap:collisions} This example shows how to detect collisions on tilemaps [Project files](https://github.com/defold/examples/tree/master/tilemap/collisions) This example uses a tilesource with two collision groups: "ground" and "danger". The tilesource uses the `tilesheet_complete.png` image for the tiles and the collision shapes (traced as outlines around the transparent pixels of each tile). The tiles belonging to the two groups have been "painted" as can be seen by the outline around each tile. The tiles belonging to the "danger" group are purple and the tiles belonging to the "ground" group are green. Tiles with a white outline does not belong to a collision group. The tilemap component uses the tilesource: The tilemap is added to the example together with a collision object which uses the tilemap itself as collision shape. Note that there is no need to specify any collsion groups on the collision object itself. The groups defined in the tilesource (ie "ground" and "danger") will be used: Click/tap on the screen to spawn game objects that will fall and interact with the tilemap. --- Tilemap and enemy graphics made by [Kenney](https://www.kenney.nl). ## Scripts ### collisions.script ```lua function init(self) msg.post(".", "acquire_input_focus") -- <1> for i=1,10 do factory.create("#enemyfactory", vmath.vector3(math.random(100, 700), 600, 1)) -- <2> end end function on_input(self, action_id, action) if action_id == hash("mouse_button_left") and action.pressed then factory.create("#enemyfactory", vmath.vector3(action.x, action.y, 1)) -- <3> end end function on_message(self, message_id, message, sender) if message_id == hash("collision_response") then -- <4> if message.own_group == hash("danger") then -- <5> go.delete(message.other_id) -- <6> end end end --[[ 1. Acquire input for the script 2. Spawn 10 game objects at random positions near the top of the screen 3. Spawn a game object when the left mouse button (or touch) is pressed 4. Something collided with the tilemap if the received message was a `collision_response` 5. Check if something collided with a tile belonging to the collision group "danger" 6. Delete the game object that collided with the tilemap --]] ``` # Cancel timer example {#examples:timer:cancel_timer} This example shows how to create timer and cancel it anytime, using built-in timer API. [Project files](https://github.com/defold/examples/tree/master/timer/cancel_timer) The example shows how to use Defold built-in timer and uses two indicators: 1. A particlefx gui node that is triggered every 1s. 2. A text node with an information displaying. The particle fx is played every 1s showing small eruption. You can click anywhere to cancel the timer and the particlefx won't be triggered anymore. ## Scripts ### cancel_timer.gui_script ```lua function init(self) local interval = 1 -- <1> local repeating = true -- <2> self.timer = timer.delay(interval, repeating, function() -- <3> local node = gui.get_node("particlefx") -- <4> gui.play_particlefx(node) -- <5> end) msg.post(".", "acquire_input_focus") -- <6> end function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed then -- <7> timer.cancel(self.timer) -- <8> local node = gui.get_node("info") -- <9> gui.set_text(node, "Timer cancelled.") -- <10> end end --[[ 1. We will use interval of 1 (s). 2. We will be repeating the timer endlessly. 3. Start the timer with interval (1s) and repeating (true) and pass a callback function. Store the handle to the timer in self.timer. 4. Get the particle fx node. 5. Play particle fx in each call of the callback function of the timer. 6. Tell the engine that this game object wants to receive input. 7. If the user clicks. 8. Cancel the timer using the saved self.timer handle. 9. Get the text node. 10. Update text node with an information that the timer was cancelled. --]] ``` # Repeating timer example {#examples:timer:repeating_timer} This example shows how to create timer that repeats endlessly every second [Project files](https://github.com/defold/examples/tree/master/timer/repeating_timer) The example shows how to use Defold built-in timer and uses two indicators: 1. A numerical time text with seconds counter created using a text node 2. A circular time indicator created using a pie node The timer trigers updates of those two indicators every 1s to form a counter. ## Scripts ### repeating_timer.gui_script ```lua -- set value of numeric time indicator (from 0 to 60s) local function update_numeric(p) local node = gui.get_node("numeric") gui.set_text(node, tostring(p) .. "s") end -- update radial/circle time indicator by changing the fill angle local function update_radial(p) local node = gui.get_node("radial") local angle = p * 6 gui.set_fill_angle(node, angle) end function init(self) self.count = 0 -- <1> local interval = 1 -- <2> local repeating = true -- <3> timer.delay(interval, repeating, function() -- <4> self.count = self.count + 1 -- <5> local p = self.count % 60 -- <6> update_numeric(p) -- <7> update_radial(p) -- <8> end) end --[[ 1. Start the count with value 0. 2. We will use interval of 1 [s]. 3. We will be repeating the timer endlessly. 4. Start the timer with interval (1s) and repeating (true) and pass a callback function. 5. The function will be called every 1s, so increase the count by 1 each time. 6. Get the modulo of 60, because the timer will be reset every 60s. 7. Update the numeric display of seconds passed. 8. Update the radial indicator of seconds passed. --]] ``` # Trigger timer example {#examples:timer:trigger_timer} This example shows how to create timer that triggers counting every 1s and can be triggered manually and asynchronously as a reaction to user input. [Project files](https://github.com/defold/examples/tree/master/timer/trigger_timer) The example shows how to use Defold built-in timer and trigger it asynchronously and uses two indicators: 1. A counter text increased every 1s created using a text node. 2. A text node with information displayed. The timer triggers update of the counter every 1s. Click anywhere to trigger the callback of the timer asynchronously. ## Scripts ### trigger_timer.gui_script ```lua function init(self) self.count = 0 -- <1> local interval = 1 -- <2> local repeating = true -- <3> self.timer = timer.delay(interval, repeating, function() -- <4> self.count = self.count + 1 -- <5> local node = gui.get_node("counter") -- <6> gui.set_text(node, self.count) -- <7> end) msg.post(".", "acquire_input_focus") -- <8> end function on_input(self, action_id, action) if action_id == hash("touch") and action.pressed then -- <9> timer.trigger(self.timer) -- <10> end end --[[ 1. Start the count with value 0. 2. We will use interval of 1 [s]. 3. We will be repeating the timer endlessly. 4. Start the timer with interval (1s) and repeating (true) and pass a callback function. Store the handle to the timer in self.timer. 5. The function will be called every 1s, so increase the count by 1 each time. 6. Get the counter text node. 7. Update the counter text node with an increased count. 8. Tell the engine that this game object wants to receive input. 9. If the user clicks. 10. Trigger the timer's callback function asynchronously using the saved self.timer handle. --]] ```