diff --git a/examples/3d-flight/3d-flight.json b/examples/3d-flight/3d-flight.json new file mode 100644 index 000000000..dfb2880d3 --- /dev/null +++ b/examples/3d-flight/3d-flight.json @@ -0,0 +1,35299 @@ +{ + "firstLayout": "", + "gdVersion": { + "build": 266, + "major": 5, + "minor": 6, + "revision": 0 + }, + "properties": { + "adaptGameResolutionAtRuntime": true, + "antialiasingMode": "MSAA", + "antialisingEnabledOnMobile": false, + "folderProject": false, + "orientation": "landscape", + "packageName": "com.example.gamename", + "pixelsRounding": false, + "projectUuid": "4780ed1b-1535-4318-847a-d4c475e6bc61", + "scaleMode": "linear", + "sizeOnStartupMode": "adaptWidth", + "templateSlug": "", + "version": "1.0.0", + "name": "3d-flight", + "description": "", + "author": "", + "windowWidth": 1280, + "windowHeight": 720, + "latestCompilationDirectory": "", + "maxFPS": 60, + "minFPS": 20, + "verticalSync": false, + "platformSpecificAssets": {}, + "loadingScreen": { + "backgroundColor": 0, + "backgroundFadeInDuration": 0.2, + "backgroundImageResourceName": "", + "gdevelopLogoStyle": "light", + "logoAndProgressFadeInDuration": 0.2, + "logoAndProgressLogoFadeInDelay": 0, + "minDuration": 1.5, + "progressBarColor": 16777215, + "progressBarHeight": 20, + "progressBarMaxWidth": 200, + "progressBarMinWidth": 40, + "progressBarWidthPercent": 30, + "showGDevelopSplash": true, + "showProgressBar": true + }, + "watermark": { + "placement": "bottom-left", + "showWatermark": true + }, + "authorIds": [], + "authorUsernames": [], + "categories": [], + "playableDevices": [ + "mobile" + ], + "extensionProperties": [], + "platforms": [ + { + "name": "GDevelop JS platform" + } + ], + "currentPlatform": "GDevelop JS platform" + }, + "resources": { + "resources": [ + { + "file": "assets/Cubemap_Sky_04-512x512_Back.png", + "kind": "image", + "metadata": "", + "name": "assets\\Cubemap_Sky_04-512x512_Back.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Cubemap_Sky_04-512x512_Bottom.png", + "kind": "image", + "metadata": "", + "name": "assets\\Cubemap_Sky_04-512x512_Bottom.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Cubemap_Sky_04-512x512_Front.png", + "kind": "image", + "metadata": "", + "name": "assets\\Cubemap_Sky_04-512x512_Front.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Cubemap_Sky_04-512x512_Left.png", + "kind": "image", + "metadata": "", + "name": "assets\\Cubemap_Sky_04-512x512_Left.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Cubemap_Sky_04-512x512_Right.png", + "kind": "image", + "metadata": "", + "name": "assets\\Cubemap_Sky_04-512x512_Right.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Cubemap_Sky_04-512x512_Top.png", + "kind": "image", + "metadata": "", + "name": "assets\\Cubemap_Sky_04-512x512_Top.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Spaceship Fernando The Flamingo.glb", + "kind": "model3D", + "metadata": "", + "name": "Spaceship Fernando The Flamingo.glb", + "userAdded": false, + "origin": { + "identifier": "https://asset-resources.gdevelop.io/public-resources/3D Space Station/Vehicles/Spaceship/099b5d140ec15c846a52cc28e336d1bedccab4692d55c526b8459699aa6d5c59_Spaceship Fernando The Flamingo.glb", + "name": "Spaceship Fernando The Flamingo.glb" + } + }, + { + "file": "assets/Bed Bunk.glb", + "kind": "model3D", + "metadata": "", + "name": "Bed Bunk.glb", + "userAdded": false, + "origin": { + "identifier": "https://asset-resources.gdevelop.io/public-resources/3D Furniture/furniture/a47d4bc4fb5b10b35ae2157f09952973d57fda797e83b6be2d2d0e69581b58bc_Bed Bunk.glb", + "name": "Bed Bunk.glb" + } + }, + { + "file": "assets/Chair Cushion.glb", + "kind": "model3D", + "metadata": "", + "name": "Chair Cushion.glb", + "userAdded": false, + "origin": { + "identifier": "https://asset-resources.gdevelop.io/public-resources/3D Furniture/furniture/3d60cc98ac1987f46070d50080e74815a0628b2b9fa85f9af11ae029284fd434_Chair Cushion.glb", + "name": "Chair Cushion.glb" + } + }, + { + "file": "assets/Bookcase Open.glb", + "kind": "model3D", + "metadata": "", + "name": "Bookcase Open.glb", + "userAdded": false, + "origin": { + "identifier": "https://asset-resources.gdevelop.io/public-resources/3D Furniture/furniture/b9cdf232b08381303d8c69ab78ee98ad836b479a0cfce6f525039b0a290da469_Bookcase Open.glb", + "name": "Bookcase Open.glb" + } + }, + { + "file": "assets/Side Table.glb", + "kind": "model3D", + "metadata": "", + "name": "Side Table.glb", + "userAdded": false, + "origin": { + "identifier": "https://asset-resources.gdevelop.io/public-resources/3D Furniture/furniture/e503f1f9ce967be7890d35fea844362c0e66ab24aed200e2ee56b502c45c33cd_Side Table.glb", + "name": "Side Table.glb" + } + }, + { + "file": "assets/Desk.glb", + "kind": "model3D", + "metadata": "", + "name": "Desk.glb", + "userAdded": false, + "origin": { + "identifier": "https://asset-resources.gdevelop.io/public-resources/3D Furniture/furniture/e278706a45da26c4c1525b341648663279c87917984aaa5f2454801d91533adf_Desk.glb", + "name": "Desk.glb" + } + }, + { + "file": "assets/Cabinet Bed Drawer Table.glb", + "kind": "model3D", + "metadata": "", + "name": "Cabinet Bed Drawer Table.glb", + "userAdded": false, + "origin": { + "identifier": "https://asset-resources.gdevelop.io/public-resources/3D Furniture/furniture/6c91e7c91fad99c11fcdb9fd56a584258ff27531819fc9f59e18a1ae6daa6c09_Cabinet Bed Drawer Table.glb", + "name": "Cabinet Bed Drawer Table.glb" + } + }, + { + "file": "assets/Doorway.glb", + "kind": "model3D", + "metadata": "", + "name": "Doorway.glb", + "userAdded": false, + "origin": { + "identifier": "https://asset-resources.gdevelop.io/public-resources/3D Furniture/5c759ba199215cb6303b1a52841cf7543bef48951421f61383e3fb17896df2eb_Doorway.glb", + "name": "Doorway.glb" + } + }, + { + "file": "assets/Floor.png", + "kind": "image", + "metadata": "{\"extension\":\".png\",\"pskl\":{},\"localFilePath\":\"assets/Floor.png\"}", + "name": "Floor", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Wall.png", + "kind": "image", + "metadata": "{\"extension\":\".png\",\"pskl\":{},\"localFilePath\":\"assets/Wall.png\"}", + "name": "Wall", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Marker.png", + "kind": "image", + "metadata": "", + "name": "assets\\Marker.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Wood.png", + "kind": "image", + "metadata": "{\"extension\":\".png\",\"pskl\":{}}", + "name": "Wood", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Transparent.png", + "kind": "image", + "metadata": "", + "name": "assets\\Transparent.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Particle.png", + "kind": "image", + "metadata": "", + "name": "assets\\Particle.png", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Red.png", + "kind": "image", + "metadata": "{\"extension\":\".png\",\"pskl\":{}}", + "name": "Red", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Yellow.png", + "kind": "image", + "metadata": "{\"extension\":\".png\",\"pskl\":{}}", + "name": "Yellow", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Green.png", + "kind": "image", + "metadata": "{\"extension\":\".png\",\"pskl\":{}}", + "name": "Green", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Blue.png", + "kind": "image", + "metadata": "{\"extension\":\".png\",\"pskl\":{}}", + "name": "Blue", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Purple.png", + "kind": "image", + "metadata": "{\"extension\":\".png\",\"pskl\":{}}", + "name": "Purple", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Pink.png", + "kind": "image", + "metadata": "{\"extension\":\".png\",\"pskl\":{}}", + "name": "Pink", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Common Tree 1.glb", + "kind": "model3D", + "metadata": "", + "name": "Common Tree 1.glb", + "userAdded": false, + "origin": { + "identifier": "https://asset-resources.gdevelop.io/public-resources/3D Rocks and Trees/Plant/7c4f3d2324ecd1f8910652478dd7bcb1ac714b260c66a562318c3f72c37bb404_Common Tree 1.glb", + "name": "Common Tree 1.glb" + } + }, + { + "file": "assets/Grass.png", + "kind": "image", + "metadata": "{\"extension\":\".png\",\"pskl\":{}}", + "name": "Grass", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Book 5.glb", + "kind": "model3D", + "metadata": "", + "name": "Book 5.glb", + "userAdded": false, + "origin": { + "identifier": "https://asset-resources.gdevelop.io/public-resources/Fantasy Props MegaKit - Standard/51b3d516c5257a47a2d9e3c2166a67de273605dfa445bbf22988c3bc9567d383_Book 5.glb", + "name": "Book 5.glb" + } + }, + { + "file": "assets/White.png", + "kind": "image", + "metadata": "{\"extension\":\".png\",\"pskl\":{}}", + "name": "White", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Ceiling.png", + "kind": "image", + "metadata": "{\"extension\":\".png\",\"pskl\":{}}", + "name": "Ceiling", + "smoothed": true, + "userAdded": false + }, + { + "file": "assets/Spiky Ball.glb", + "kind": "model3D", + "metadata": "", + "name": "Spiky Ball.glb", + "userAdded": false, + "origin": { + "identifier": "https://asset-resources.gdevelop.io/public-resources/3D Platformer Game Kit/Props/b3083ee63f966b628eba08d319b0ad1d508687a733c74a3923425f9e888567a3_Spiky Ball.glb", + "name": "Spiky Ball.glb" + } + }, + { + "file": "assets/Bottle Ketchup.glb", + "kind": "model3D", + "metadata": "", + "name": "Bottle Ketchup.glb", + "userAdded": false, + "origin": { + "identifier": "https://asset-resources.gdevelop.io/public-resources/3D Food/Food/7ba9cd4e680a78bcdd6e7a54366442cb53b8c2ebd1abc5ec5577f512ae025247_Bottle Ketchup.glb", + "name": "Bottle Ketchup.glb" + } + }, + { + "file": "assets/Male Casual.glb", + "kind": "model3D", + "metadata": "", + "name": "Male Casual.glb", + "userAdded": false, + "origin": { + "identifier": "https://asset-resources.gdevelop.io/public-resources/3D Animated Characters/Character/9e45e58c10682186015966e9739499ac835b807ab0cb20be0f648458ecf44a0d_Male Casual.glb", + "name": "Male Casual.glb" + } + } + ] + }, + "objects": [], + "objectsFolderStructure": { + "folderName": "__ROOT" + }, + "objectsGroups": [], + "variables": [], + "layouts": [ + { + "b": 43, + "disableInputWhenNotFocused": true, + "mangledName": "Untitled_32scene", + "name": "Untitled scene", + "r": 43, + "standardSortMethod": true, + "stopSoundsOnStartup": true, + "title": "", + "v": 43, + "uiSettings": { + "grid": true, + "gridType": "rectangular", + "gridWidth": 80, + "gridHeight": 80, + "gridDepth": 80, + "gridOffsetX": 0, + "gridOffsetY": 0, + "gridOffsetZ": 0, + "gridColor": 16098851, + "gridAlpha": 0.5, + "snap": true, + "zoomFactor": 2.9678640778695278, + "windowMask": false, + "selectedLayer": "", + "gameEditorMode": "embedded-game" + }, + "objectsGroups": [ + { + "name": "Obstacle", + "objects": [ + { + "name": "Floor" + }, + { + "name": "Wall" + }, + { + "name": "Bed" + }, + { + "name": "Chair" + }, + { + "name": "Bookcase" + }, + { + "name": "Side_Table" + }, + { + "name": "Desk" + }, + { + "name": "Cabinet_Bed_Drawer_Table" + }, + { + "name": "Doorway" + }, + { + "name": "Cube" + }, + { + "name": "Book" + }, + { + "name": "Ceiling" + }, + { + "name": "HiddenWall" + } + ] + }, + { + "name": "Spark", + "objects": [ + { + "name": "YellowSpark" + }, + { + "name": "RedSpark" + } + ] + }, + { + "name": "DynamicObstacle", + "objects": [ + { + "name": "Cube" + }, + { + "name": "Book" + } + ] + } + ], + "variables": [ + { + "name": "oldX", + "type": "number", + "value": 0 + } + ], + "instances": [ + { + "angle": 0, + "customSize": true, + "height": 560, + "layer": "", + "locked": true, + "name": "Floor", + "persistentUuid": "5e450e46-e775-4bdf-bcc8-47b67809f86b", + "width": 560, + "x": 0, + "y": 0, + "z": -100, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 180, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "", + "name": "Spaceship", + "persistentUuid": "f9ea5946-3aad-45b3-acb6-e32c675c5e69", + "width": 0, + "x": 274, + "y": 280, + "z": 160, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 181, + "layer": "", + "locked": true, + "name": "Bed", + "persistentUuid": "29caf98f-e586-4d68-a0e2-ba0b1e1f8236", + "width": 94.3844907693105, + "x": 400, + "y": 0, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 64.62884473178701, + "layer": "", + "locked": true, + "name": "Desk", + "persistentUuid": "cdf98546-7d43-4503-95a2-0bd2c96a8a58", + "width": 121, + "x": 0, + "y": 320, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 110, + "customSize": false, + "height": 33.043478153829106, + "layer": "", + "name": "Chair", + "persistentUuid": "fabfe259-299e-4bfd-942d-5ba8fb224547", + "width": 33.043478153829085, + "x": 102, + "y": 347, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 35.94436541856759, + "layer": "", + "locked": true, + "name": "Cabinet_Bed_Drawer_Table", + "persistentUuid": "0d7a0a2f-948c-447b-b77e-23ce98f4fa5c", + "width": 44, + "x": 320, + "y": 0, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 18.758992542243874, + "layer": "", + "locked": true, + "name": "Doorway", + "persistentUuid": "580c902c-3708-47f1-a3fd-0e3b37096bd1", + "width": 80.39568478890051, + "x": 160, + "y": -10, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 41.1931848315109, + "layer": "", + "locked": true, + "name": "Bookcase", + "persistentUuid": "16916531-4335-4b51-9268-304dfd578c2f", + "width": 65.90909671253944, + "x": 80, + "y": 518, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 200, + "height": 10, + "layer": "", + "locked": true, + "name": "Wall", + "persistentUuid": "da2af813-c7af-4f32-9724-cd9702fabad0", + "width": 560, + "x": 0, + "y": -10, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 560, + "layer": "", + "locked": true, + "name": "Wall", + "persistentUuid": "4fe85e6e-4c3e-4603-b23d-31ea2db6c723", + "width": 10, + "x": -10, + "y": 0, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 100, + "layer": "", + "name": "Cube", + "persistentUuid": "aef14b2e-90d8-4b63-9d02-f622fd3da8ac", + "width": 100, + "x": 240, + "y": 240, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 180, + "customSize": false, + "height": 10, + "layer": "", + "name": "Cube", + "persistentUuid": "325f3866-da2a-41f6-a815-cc864caef9f1", + "rotationX": -90, + "rotationY": 90, + "width": 10, + "x": 241, + "y": 239, + "z": 10, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 90, + "customSize": false, + "height": 10, + "layer": "", + "name": "Cube", + "persistentUuid": "0b1a9ff5-3f4a-46cf-a017-1505457ce827", + "rotationX": 90, + "width": 10, + "x": 239, + "y": 240, + "z": 20, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": -90, + "customSize": false, + "height": 10, + "layer": "", + "name": "Cube", + "persistentUuid": "c14d06dd-d78d-422a-8bf8-75aca2b72f23", + "rotationX": 90, + "width": 10, + "x": 240, + "y": 240, + "z": 30, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "UI", + "name": "Marker", + "persistentUuid": "06965f03-f45b-4d60-81d6-3a3eeb6db5de", + "width": 0, + "x": 0, + "y": -160, + "zOrder": 2, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 8, + "height": 8, + "layer": "", + "locked": true, + "name": "Wood", + "persistentUuid": "96575a40-0a51-4b98-b674-be6e05ea7657", + "width": 160, + "x": 320, + "y": 552, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 8, + "height": 8, + "layer": "", + "locked": true, + "name": "Wood", + "persistentUuid": "f232676f-20ae-488b-b94a-5302116b37db", + "width": 160, + "x": 320, + "y": 552, + "z": 160, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 168, + "height": 8, + "layer": "", + "locked": true, + "name": "Wood", + "persistentUuid": "e50d00e7-b91d-412c-8c39-80290d2f44bd", + "width": 8, + "x": 320, + "y": 552, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 168, + "height": 8, + "layer": "", + "locked": true, + "name": "Wood", + "persistentUuid": "86daaaf4-a1bf-4ae5-9fdf-eb316f883b97", + "width": 8, + "x": 472, + "y": 552, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 4, + "height": 4, + "layer": "", + "locked": true, + "name": "Wood", + "persistentUuid": "6719fa8d-2b46-431f-abd4-b9cc5b019d04", + "width": 160, + "x": 320, + "y": 556, + "z": 8, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 4, + "height": 4, + "layer": "", + "locked": true, + "name": "Wood", + "persistentUuid": "ccfa8605-4c67-4dcd-9d19-f67c1d223e76", + "width": 160, + "x": 320, + "y": 556, + "z": 156, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 168, + "height": 4, + "layer": "", + "locked": true, + "name": "Wood", + "persistentUuid": "ecd3d9d0-54d7-4255-9add-b75b329bd390", + "width": 4, + "x": 468, + "y": 556, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 168, + "height": 4, + "layer": "", + "locked": true, + "name": "Wood", + "persistentUuid": "e20698d9-fa8a-4a60-8f0e-b8a45e3c685a", + "width": 4, + "x": 328, + "y": 556, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 168, + "height": 4, + "layer": "", + "locked": true, + "name": "Wood", + "persistentUuid": "ae40e6b3-082f-49ec-8fb7-e896ad80e9ed", + "width": 8, + "x": 396, + "y": 556, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 10, + "layer": "", + "locked": true, + "name": "Wall", + "persistentUuid": "05213534-f4bc-4065-b5e2-f9e7cb5d3cd1", + "width": 320, + "x": 0, + "y": 560, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 200, + "height": 10, + "layer": "", + "locked": true, + "name": "Wall", + "persistentUuid": "1d681026-eaf8-419f-ba67-f8346f07620d", + "width": 560, + "x": 0, + "y": -10, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 200, + "height": 10, + "layer": "", + "locked": true, + "name": "Wall", + "persistentUuid": "96ac49ec-28c5-4964-a6a3-4eafb68d0363", + "width": 80, + "x": 480, + "y": 560, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 40, + "height": 10, + "layer": "", + "locked": true, + "name": "Wall", + "persistentUuid": "64c0f035-8ae4-45af-95ba-24cafa5fc2c2", + "width": 160, + "x": 320, + "y": 560, + "z": 160, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 200, + "height": 10, + "layer": "", + "locked": true, + "name": "HiddenWall", + "persistentUuid": "5ebf6b86-1fe0-47eb-8335-46d1bca55ea1", + "width": 160, + "x": 320, + "y": 560, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 560, + "layer": "", + "locked": true, + "name": "Wall", + "persistentUuid": "068cc8ea-b81c-4f9c-82e8-0097961b5101", + "width": 10, + "x": 560, + "y": 0, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 170.3048631264634, + "layer": "", + "locked": true, + "name": "Tree", + "persistentUuid": "7a87081b-b019-4cf8-bfa3-1583b64a1fe4", + "width": 250, + "x": 560, + "y": 870, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "depth": 100, + "height": 3200, + "layer": "", + "locked": true, + "name": "Grass", + "persistentUuid": "2947fde1-da5c-4df7-bfc0-0b96bdf17077", + "width": 3200, + "x": -1200, + "y": 560, + "z": -100, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 116, + "customSize": false, + "height": 170.3048631264634, + "layer": "", + "locked": true, + "name": "Tree", + "persistentUuid": "05634207-1132-4c77-8847-71be1d4436e3", + "width": 250, + "x": 240, + "y": 1360, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 240, + "customSize": false, + "height": 170.3048631264634, + "layer": "", + "locked": true, + "name": "Tree", + "persistentUuid": "4f750d81-525c-4118-a32f-e2db9c19340e", + "width": 250, + "x": -240, + "y": 1040, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 6.674198099498667, + "layer": "", + "name": "Book", + "persistentUuid": "24ac7d43-5445-4417-aa39-8fb60d2c2700", + "rotationY": 355, + "width": 9, + "x": 132, + "y": 539, + "z": 61, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 6.674198099498667, + "layer": "", + "name": "Book", + "persistentUuid": "b5bba513-5a97-4c24-899a-85c216e9b20b", + "width": 9, + "x": 125, + "y": 539, + "z": 61, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 6.674198099498667, + "layer": "", + "name": "Book", + "persistentUuid": "114a0be4-f8f0-457e-b720-3236a359065b", + "width": 9, + "x": 119, + "y": 539, + "z": 61, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 6.674198099498667, + "layer": "", + "name": "Book", + "persistentUuid": "c0124303-c03e-4d41-b1cb-82292068f545", + "width": 9, + "x": 113, + "y": 539, + "z": 61, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 6.674198099498667, + "layer": "", + "name": "Book", + "persistentUuid": "88fcb0c9-47f9-47b8-ae78-7f81fb3fe8c3", + "width": 9, + "x": 107, + "y": 539, + "z": 61, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 152, + "customSize": false, + "height": 19.16325889527798, + "layer": "", + "name": "Book", + "persistentUuid": "0c36e40c-57de-437d-9490-297a7bc13f06", + "rotationY": 90, + "width": 5.727619305253034, + "x": 36, + "y": 400, + "z": 54, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": true, + "height": 560, + "layer": "", + "locked": true, + "name": "Ceiling", + "persistentUuid": "16637982-2366-485f-9fe9-00e18bd5fea4", + "width": 560, + "x": 0, + "y": 0, + "z": 200, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 10, + "layer": "", + "name": "Cube", + "persistentUuid": "92d94c7b-05ac-4c4f-8995-f7d3f820980c", + "width": 10, + "x": 272, + "y": 243, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 1.5, + "layer": "", + "name": "BottleKetchup", + "persistentUuid": "45b0bc46-6b9d-4289-880b-a5b5bdd0a5ae", + "width": 8, + "x": 480, + "y": 560, + "z": 235.2731289363229, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 1.5, + "layer": "", + "name": "BottleKetchup", + "persistentUuid": "b40babc6-fa64-4225-8651-9b44cf08a965", + "width": 8, + "x": 560, + "y": 640, + "z": 80, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 156, + "layer": "", + "name": "Male_Casual", + "persistentUuid": "8d12fe6a-f0a2-4621-837f-0af07bc76aef", + "width": 28.298850915139454, + "x": 560, + "y": 640, + "zOrder": 0, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + } + ], + "objects": [ + { + "assetStoreId": "", + "name": "Floor", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Static", + "bullet": false, + "fixedRotation": false, + "shape": "Box", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0.3, + "restitution": 0.1, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "width": 100, + "height": 100, + "depth": 100, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "frontFaceResourceName": "Floor", + "backFaceResourceName": "", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "", + "rightFaceResourceName": "", + "topFaceResourceName": "", + "bottomFaceResourceName": "", + "frontFaceVisible": true, + "backFaceVisible": false, + "leftFaceVisible": false, + "rightFaceVisible": false, + "topFaceVisible": false, + "bottomFaceVisible": false, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "materialType": "StandardWithoutMetalness", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": true + } + }, + { + "assetStoreId": "7eb8798d1380ef3a7ff7fb915355bccedb961714ea575acc23f7ce371ab97b16", + "name": "Spaceship", + "persistentUuid": "f0033831-6c23-468a-8860-ecad9cac6cfc", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "FireBullet", + "type": "FireBullet::FireBullet", + "FireCooldown": 0.25, + "HasJustFired": false, + "RotateBullet": true, + "FiringArc": 45, + "BulletQuantity": 1, + "AngleVariance": 0, + "BulletSpeedVariance": 0, + "AmmoQuantity": 0, + "ShotsPerReload": 0, + "ReloadDuration": 1, + "MaxAmmo": 0, + "ShotsBeforeNextReload": 0, + "TotalShotsFired": 0, + "TotalBulletsCreated": 0, + "StartingAmmo": 0, + "TotalReloadsCompleted": 0, + "UnlimitedAmmo": true, + "ReloadInProgress": false, + "HeatIncreasePerShot": 0, + "HeatLevel": 0, + "AutomaticReloading": true, + "OverheatDuration": 0, + "LinearCoolingRate": 0.1, + "ExponentialCoolingRate": 0.3, + "BulletLayer": "", + "RandomizedAngle": 0, + "ForwardX": 2.0247e-320, + "ForwardY": 2.0247e-320, + "ForwardZ": 2.0247e-320 + }, + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Dynamic", + "bullet": false, + "fixedRotation": true, + "shape": "Sphere", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 40, + "friction": 0.3, + "restitution": 0.1, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 0, + "layers": 17, + "masks": 17 + }, + { + "name": "PhysicsAirplane3D", + "type": "PhysicsAirplane3D::PhysicsAirplane3D", + "Physics3DBehavior": "Physics3D", + "CurrentForwardSpeed": 0, + "ForwardSpeedMax": 50, + "ForwardX": 0, + "ForwardY": 0, + "ForwardZ": 0, + "Object3D": "Object3D", + "HorizontalAngularSpeedMax": 60, + "VerticalAngularSpeedMax": 60, + "SpinMax": 60 + }, + { + "name": "ThirdPersonCamera", + "type": "ThirdPersonCamera::ThirdPersonCamera", + "Object3D": "Object3D", + "RotationHalfwayDuration": 0.25, + "ElevationHalfwayDuration": 0.25, + "TranslationZHalfwayDuration": 0.125, + "Distance": 13, + "OffsetX": 0, + "OffsetY": -5, + "OffsetZ": 4, + "RotationAngleOffset": 0, + "ElevationAngleOffset": 0, + "FollowFreeAreaZMax": 0, + "FollowFreeAreaZMin": 0, + "RotationLogSpeed": 2.0247e-320, + "ElevationLogSpeed": 2.0247e-320, + "TranslationZLogSpeed": 2.0247e-320, + "IsCalledManually": false, + "CameraZ": 0, + "HasJustBeenCreated": true, + "IsRotatingWithObject": true, + "IsElevatingWithObject": false, + "TargetedRotationAngle": 0, + "TargetedElevationAngle": 0, + "RotationMode": "ZYX" + } + ], + "content": { + "centerLocation": "ModelOrigin", + "crossfadeDuration": 0.10000000149011612, + "depth": 1.263626456260682, + "height": 5.569547653198243, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "Spaceship Fernando The Flamingo.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 90, + "width": 4.328316807746889, + "animations": [] + } + }, + { + "assetStoreId": "3b6ee79dde2cae874aa3672025d8ac6d75186222fe623b401cda41f7e76edd0c", + "name": "Bed", + "persistentUuid": "e11f54b7-d905-4218-a29a-a9856cda9f34", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Static", + "bullet": false, + "fixedRotation": false, + "shape": "Mesh", + "meshShapeResourceName": "", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0.3, + "restitution": 0.1, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "centerLocation": "ObjectCenter", + "crossfadeDuration": 0.10000000149011612, + "depth": 181, + "height": 181, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "Bed Bunk.glb", + "originLocation": "TopLeft", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 181, + "animations": [] + } + }, + { + "assetStoreId": "835e2f69cc66a12ebb64bce06cd68b5c3d0c5c9474acf73a4ecd86e818de078e", + "name": "Chair", + "persistentUuid": "7fb5eb13-6ff3-49b1-8e89-bbe6303e6012", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Static", + "bullet": false, + "fixedRotation": false, + "shape": "Mesh", + "meshShapeResourceName": "", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0.3, + "restitution": 0.1, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "centerLocation": "ModelOrigin", + "crossfadeDuration": 0.10000000149011612, + "depth": 76, + "height": 76, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "Chair Cushion.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 76, + "animations": [] + } + }, + { + "assetStoreId": "f43bb2cc1a83d433153cb297eb3218371b1f72eb72d003e38eba419ec6f5e611", + "name": "Bookcase", + "persistentUuid": "ef83bf1a-fd0c-4c9c-8490-786f18b8271c", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Static", + "bullet": false, + "fixedRotation": false, + "shape": "Mesh", + "meshShapeResourceName": "", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0.3, + "restitution": 0.1, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "centerLocation": "ObjectCenter", + "crossfadeDuration": 0.10000000149011612, + "depth": 144.9711893951893, + "height": 41.18500000000004, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "Bookcase Open.glb", + "originLocation": "TopLeft", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 65.89600098192692, + "animations": [] + } + }, + { + "assetStoreId": "604eabc09ee8aaa21bbd9d5ebaf16d8bd518c9c88ea15b8c83a67b2fff8fbb01", + "name": "Side_Table", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "ModelOrigin", + "crossfadeDuration": 0.10000000149011612, + "depth": 88, + "height": 88, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "Side Table.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 88, + "animations": [] + } + }, + { + "assetStoreId": "a0014055ae529545fc4005e44b4f8ac3d3ad3646c658aceaf5371c8efdba935e", + "name": "Desk", + "persistentUuid": "6721b46a-dcc5-4d0c-9bf2-23f114c79cba", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Static", + "bullet": false, + "fixedRotation": false, + "shape": "Mesh", + "meshShapeResourceName": "", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0.3, + "restitution": 0.1, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "centerLocation": "ObjectCenter", + "crossfadeDuration": 0.10000000149011612, + "depth": 63.32729980289938, + "height": 120.99748450282964, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "Desk.glb", + "originLocation": "TopLeft", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 90, + "width": 64.62750114768745, + "animations": [] + } + }, + { + "assetStoreId": "742aa2447f5d3c5f1d167e5cb6bd1718b6764d6e1d6bb8c023ed8120d0de0a07", + "name": "Cabinet_Bed_Drawer_Table", + "persistentUuid": "4fca05e4-e5ad-4ce4-a14d-fbe6fca31b6b", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Static", + "bullet": false, + "fixedRotation": false, + "shape": "Mesh", + "meshShapeResourceName": "", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0.3, + "restitution": 0.1, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "centerLocation": "ObjectCenter", + "crossfadeDuration": 0.10000000149011612, + "depth": 44, + "height": 44, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "Cabinet Bed Drawer Table.glb", + "originLocation": "TopLeft", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 44, + "animations": [] + } + }, + { + "assetStoreId": "12ea1d8405e0309c10ffb849bb61d7ed228d410338fe051648fdc0a0862e7a56", + "name": "Doorway", + "persistentUuid": "d6402442-27dd-49e9-847e-bc4e38b9de94", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Static", + "bullet": false, + "fixedRotation": false, + "shape": "Box", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0.3, + "restitution": 0.1, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "centerLocation": "ObjectCenter", + "crossfadeDuration": 0.10000000149011612, + "depth": 167, + "height": 167, + "isCastingShadow": false, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "Doorway.glb", + "originLocation": "TopLeft", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 0, + "width": 167, + "animations": [] + } + }, + { + "assetStoreId": "", + "name": "Wall", + "persistentUuid": "75028ab3-3f50-4b67-b84a-47c86e08484d", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Static", + "bullet": false, + "fixedRotation": false, + "shape": "Box", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0.3, + "restitution": 0.1, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "width": 100, + "height": 10, + "depth": 200, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "frontFaceResourceName": "", + "backFaceResourceName": "", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "Wall", + "rightFaceResourceName": "Wall", + "topFaceResourceName": "Wall", + "bottomFaceResourceName": "Wall", + "frontFaceVisible": false, + "backFaceVisible": false, + "leftFaceVisible": true, + "rightFaceVisible": true, + "topFaceVisible": true, + "bottomFaceVisible": true, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": true, + "rightFaceResourceRepeat": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceRepeat": true, + "materialType": "StandardWithoutMetalness", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": true + } + }, + { + "assetStoreId": "", + "name": "Cube", + "persistentUuid": "5b4b46f8-7b6b-41ec-b65e-04e7fa106e59", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Dynamic", + "bullet": false, + "fixedRotation": false, + "shape": "Box", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0.3, + "restitution": 0.1, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "width": 10, + "height": 10, + "depth": 10, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "frontFaceResourceName": "Red", + "backFaceResourceName": "Yellow", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "Green", + "rightFaceResourceName": "Blue", + "topFaceResourceName": "Purple", + "bottomFaceResourceName": "Pink", + "frontFaceVisible": true, + "backFaceVisible": true, + "leftFaceVisible": true, + "rightFaceVisible": true, + "topFaceVisible": true, + "bottomFaceVisible": true, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "materialType": "StandardWithoutMetalness", + "tint": "255;255;255", + "isCastingShadow": true, + "isReceivingShadow": true + } + }, + { + "adaptCollisionMaskAutomatically": true, + "assetStoreId": "", + "name": "Marker", + "type": "Sprite", + "updateIfNotVisible": false, + "variables": [], + "effects": [], + "behaviors": [], + "animations": [ + { + "name": "", + "useMultipleDirections": false, + "directions": [ + { + "looping": false, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "assets\\Marker.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 64, + "y": 64 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [ + [ + { + "x": 0, + "y": 0 + }, + { + "x": 64, + "y": 0 + }, + { + "x": 64, + "y": 64 + }, + { + "x": 0, + "y": 64 + } + ] + ] + } + ] + } + ] + } + ] + }, + { + "assetStoreId": "", + "name": "Wood", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Static", + "bullet": false, + "fixedRotation": false, + "shape": "Box", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0.3, + "restitution": 0.1, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "width": 100, + "height": 100, + "depth": 100, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "frontFaceResourceName": "Wood", + "backFaceResourceName": "Wood", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "Wood", + "rightFaceResourceName": "Wood", + "topFaceResourceName": "Wood", + "bottomFaceResourceName": "Wood", + "frontFaceVisible": true, + "backFaceVisible": true, + "leftFaceVisible": true, + "rightFaceVisible": true, + "topFaceVisible": true, + "bottomFaceVisible": true, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "materialType": "StandardWithoutMetalness", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": false + } + }, + { + "assetStoreId": "", + "name": "HiddenWall", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Static", + "bullet": false, + "fixedRotation": false, + "shape": "Box", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0.3, + "restitution": 0.1, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "width": 100, + "height": 10, + "depth": 200, + "enableTextureTransparency": true, + "facesOrientation": "Y", + "frontFaceResourceName": "", + "backFaceResourceName": "", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "assets\\Transparent.png", + "rightFaceResourceName": "assets\\Transparent.png", + "topFaceResourceName": "assets\\Transparent.png", + "bottomFaceResourceName": "assets\\Transparent.png", + "frontFaceVisible": false, + "backFaceVisible": false, + "leftFaceVisible": true, + "rightFaceVisible": true, + "topFaceVisible": true, + "bottomFaceVisible": true, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "materialType": "StandardWithoutMetalness", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": false + } + }, + { + "assetStoreId": "", + "name": "YellowSpark", + "type": "ParticleEmitter3D::ParticleEmitter3D", + "variant": "", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "StartColor": "255;230;145", + "EndOpacity": 255, + "StartOpacity": 128, + "EndScale": 0, + "SpayConeAngle": 45, + "RotationY": -90, + "StartSpeedMin": 50, + "StartSpeedMax": 100, + "LifespanMax": 0.5, + "LifespanMin": 0.25, + "Duration": 0.0625, + "Flow": 15, + "StartSizeMin": 1, + "EndColor": "255;230;142", + "Blending": "Normal", + "StartSizeMax": 2, + "Gravity": 200, + "GravityTop": "Z+" + }, + "childrenContent": { + "Particle": { + "adaptCollisionMaskAutomatically": true, + "updateIfNotVisible": false, + "animations": [ + { + "name": "Image", + "useMultipleDirections": false, + "directions": [ + { + "looping": false, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "assets\\Particle.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [ + [ + { + "x": 0, + "y": 0 + }, + { + "x": 32, + "y": 0 + }, + { + "x": 32, + "y": 32 + }, + { + "x": 0, + "y": 32 + } + ] + ] + } + ] + } + ] + } + ] + } + } + }, + { + "assetStoreId": "", + "name": "RedSpark", + "type": "ParticleEmitter3D::ParticleEmitter3D", + "variant": "", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "StartColor": "207;73;20", + "EndOpacity": 255, + "StartOpacity": 128, + "EndScale": 0, + "SpayConeAngle": 45, + "RotationY": -90, + "StartSpeedMin": 50, + "StartSpeedMax": 100, + "LifespanMax": 0.5, + "LifespanMin": 0.25, + "Duration": 0.0625, + "Flow": 15, + "StartSizeMin": 1, + "EndColor": "207;73;20", + "Blending": "Normal", + "StartSizeMax": 2, + "Gravity": 200, + "GravityTop": "Z+" + }, + "childrenContent": { + "Particle": { + "adaptCollisionMaskAutomatically": true, + "updateIfNotVisible": false, + "animations": [ + { + "name": "Image", + "useMultipleDirections": false, + "directions": [ + { + "looping": false, + "timeBetweenFrames": 0.08, + "sprites": [ + { + "hasCustomCollisionMask": true, + "image": "assets\\Particle.png", + "points": [], + "originPoint": { + "name": "origine", + "x": 0, + "y": 0 + }, + "centerPoint": { + "automatic": true, + "name": "centre", + "x": 0, + "y": 0 + }, + "customCollisionMask": [ + [ + { + "x": 0, + "y": 0 + }, + { + "x": 32, + "y": 0 + }, + { + "x": 32, + "y": 32 + }, + { + "x": 0, + "y": 32 + } + ] + ] + } + ] + } + ] + } + ] + } + } + }, + { + "assetStoreId": "16fac9714ba0a9eb3c83984910c70b11affca1b4e6a8bed49c22af1d30f957da", + "name": "Tree", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "centerLocation": "ModelOrigin", + "crossfadeDuration": 0.10000000149011612, + "depth": 250, + "height": 250, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "Common Tree 1.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": -90, + "width": 250, + "animations": [] + } + }, + { + "assetStoreId": "", + "name": "Grass", + "persistentUuid": "5e6a0ef1-d268-4092-99e5-80622d3d8ca5", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 100, + "height": 100, + "depth": 100, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "frontFaceResourceName": "Grass", + "backFaceResourceName": "", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "", + "rightFaceResourceName": "", + "topFaceResourceName": "", + "bottomFaceResourceName": "", + "frontFaceVisible": true, + "backFaceVisible": false, + "leftFaceVisible": false, + "rightFaceVisible": false, + "topFaceVisible": false, + "bottomFaceVisible": false, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "materialType": "StandardWithoutMetalness", + "tint": "255;255;255", + "isCastingShadow": true, + "isReceivingShadow": true + } + }, + { + "assetStoreId": "4991e0451b7d81e01e5a11af45aaaaa1fc5f9552ff23fcad30826ebf0d88103c", + "name": "Book", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Dynamic", + "bullet": false, + "fixedRotation": false, + "shape": "Box", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0.3, + "restitution": 0.1, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "centerLocation": "ModelOrigin", + "crossfadeDuration": 0.10000000149011612, + "depth": 25.841206312179565, + "height": 19.16325889527798, + "isCastingShadow": false, + "isReceivingShadow": false, + "keepAspectRatio": true, + "materialType": "Basic", + "modelResourceName": "Book 5.glb", + "originLocation": "BottomCenterZ", + "rotationX": 0, + "rotationY": 0, + "rotationZ": -90, + "width": 5.727619305253034, + "animations": [] + } + }, + { + "assetStoreId": "", + "name": "Hitbox", + "persistentUuid": "7350a94a-4f98-44dc-a656-ee55eb7987f7", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Static", + "bullet": false, + "fixedRotation": false, + "shape": "Box", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0.3, + "restitution": 0.1, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "width": 10, + "height": 10, + "depth": 10, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "frontFaceResourceName": "Red", + "backFaceResourceName": "Red", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "Red", + "rightFaceResourceName": "Red", + "topFaceResourceName": "Red", + "bottomFaceResourceName": "Red", + "frontFaceVisible": true, + "backFaceVisible": true, + "leftFaceVisible": true, + "rightFaceVisible": true, + "topFaceVisible": true, + "bottomFaceVisible": true, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "materialType": "StandardWithoutMetalness", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": false + } + }, + { + "assetStoreId": "", + "name": "Ceiling", + "persistentUuid": "18e8c5a8-7299-4b33-aad2-37389357cadd", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Static", + "bullet": false, + "fixedRotation": false, + "shape": "Box", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 1, + "friction": 0.3, + "restitution": 0.1, + "linearDamping": 0.1, + "angularDamping": 0.1, + "gravityScale": 1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "width": 100, + "height": 100, + "depth": 100, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "frontFaceResourceName": "", + "backFaceResourceName": "Ceiling", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "", + "rightFaceResourceName": "", + "topFaceResourceName": "", + "bottomFaceResourceName": "", + "frontFaceVisible": false, + "backFaceVisible": true, + "leftFaceVisible": false, + "rightFaceVisible": false, + "topFaceVisible": false, + "bottomFaceVisible": false, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "materialType": "Basic", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": false + } + }, + { + "assetStoreId": "2a32220b97261b7d25bfac750227a933a6b98dbf244803baba29c09bfb260144", + "name": "SpikyBall", + "persistentUuid": "e8f9c1f0-4e42-4fc6-933a-bd1bfb28f079", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Dynamic", + "bullet": false, + "fixedRotation": false, + "shape": "Sphere", + "shapeOrientation": "Z", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 0.1, + "friction": 0.3, + "restitution": 0.5, + "linearDamping": 0.001, + "angularDamping": 0.001, + "gravityScale": 0.1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "centerLocation": "CenteredOnZ", + "crossfadeDuration": 0.10000000149011612, + "depth": 2, + "height": 2, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "Spiky Ball.glb", + "originLocation": "ModelOrigin", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 90, + "width": 2, + "animations": [] + } + }, + { + "assetStoreId": "d8dbeeda69bcc73dfea92f1612b271dda441199d3465ce94949fc92ec63e3799", + "name": "BottleKetchup", + "persistentUuid": "68feedd8-b094-4a94-8448-56d03d160ce4", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Dynamic", + "bullet": false, + "fixedRotation": false, + "shape": "Capsule", + "shapeOrientation": "X", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 0.1, + "friction": 0.3, + "restitution": 0.5, + "linearDamping": 0, + "angularDamping": 0, + "gravityScale": 0.1, + "layers": 17, + "masks": 17 + } + ], + "content": { + "centerLocation": "ObjectCenter", + "crossfadeDuration": 0.10000000149011612, + "depth": 4, + "height": 1.5, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": false, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "Bottle Ketchup.glb", + "originLocation": "ObjectCenter", + "rotationX": 0, + "rotationY": 0, + "rotationZ": -90, + "width": 8, + "animations": [] + } + }, + { + "assetStoreId": "797c17f7ce7790d0c4c7a16ebb35c512aee72f93f953c089c15827d6f90686e2", + "name": "Male_Casual", + "persistentUuid": "79dd19a8-db04-42fc-b22b-37585d244409", + "type": "Scene3D::Model3DObject", + "variables": [], + "effects": [], + "behaviors": [ + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Dynamic", + "bullet": false, + "fixedRotation": false, + "shape": "Capsule", + "shapeOrientation": "X", + "shapeDimensionA": 0, + "shapeDimensionB": 0, + "shapeDimensionC": 0, + "shapeOffsetX": 0, + "shapeOffsetY": 0, + "shapeOffsetZ": 0, + "massCenterOffsetX": 0, + "massCenterOffsetY": 0, + "massCenterOffsetZ": 0, + "massOverride": 0, + "density": 0.1, + "friction": 0.3, + "restitution": 0.5, + "linearDamping": 0, + "angularDamping": 0, + "gravityScale": 0, + "layers": 17, + "masks": 17 + } + ], + "content": { + "centerLocation": "ObjectCenter", + "crossfadeDuration": 0.10000000149011612, + "depth": 4.844611294079944, + "height": 5.197164749163336, + "isCastingShadow": true, + "isReceivingShadow": true, + "keepAspectRatio": true, + "materialType": "StandardWithoutMetalness", + "modelResourceName": "Male Casual.glb", + "originLocation": "ObjectCenter", + "rotationX": 90, + "rotationY": 0, + "rotationZ": 90, + "width": 0.942780707807637, + "animations": [ + { + "loop": true, + "name": "Idle", + "source": "Man_Idle" + }, + { + "loop": true, + "name": "Walk", + "source": "Man_Walk" + }, + { + "loop": true, + "name": "Run", + "source": "Man_Run" + }, + { + "loop": false, + "name": "Jump", + "source": "Man_Jump" + }, + { + "loop": false, + "name": "Punch", + "source": "Man_Punch" + }, + { + "loop": false, + "name": "Death", + "source": "Man_Death" + }, + { + "loop": false, + "name": "RunningJump", + "source": "Man_RunningJump" + }, + { + "loop": false, + "name": "Roll", + "source": "Man_Roll" + }, + { + "loop": false, + "name": "Sitting", + "source": "Man_Sitting" + }, + { + "loop": false, + "name": "Standing", + "source": "Man_Standing" + }, + { + "loop": false, + "name": "SwordSlash", + "source": "Man_SwordSlash" + }, + { + "loop": false, + "name": "Clapping", + "source": "Man_Clapping" + } + ] + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Spaceship" + }, + { + "objectName": "Floor" + }, + { + "objectName": "Tree" + }, + { + "objectName": "Wall" + }, + { + "objectName": "Ceiling" + }, + { + "objectName": "HiddenWall" + }, + { + "objectName": "Cube" + }, + { + "objectName": "SpikyBall" + }, + { + "objectName": "BottleKetchup" + }, + { + "objectName": "Male_Casual" + }, + { + "objectName": "Wood" + }, + { + "objectName": "Doorway" + }, + { + "objectName": "Marker" + }, + { + "objectName": "Cabinet_Bed_Drawer_Table" + }, + { + "objectName": "Desk" + }, + { + "objectName": "Side_Table" + }, + { + "objectName": "Bookcase" + }, + { + "objectName": "Hitbox" + }, + { + "objectName": "Book" + }, + { + "objectName": "Chair" + }, + { + "objectName": "Bed" + }, + { + "objectName": "YellowSpark" + }, + { + "objectName": "RedSpark" + }, + { + "objectName": "Grass" + } + ] + }, + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "DepartScene" + }, + "parameters": [ + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ResetTimer" + }, + "parameters": [ + "", + "\"Firing\"" + ] + }, + { + "type": { + "value": "Cache" + }, + "parameters": [ + "Hitbox" + ] + } + ], + "events": [ + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetAngle" + }, + "parameters": [ + "Spaceship", + "=", + "180" + ] + } + ] + }, + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ActivateBehavior" + }, + "parameters": [ + "Spaceship", + "ThirdPersonCamera", + "no" + ] + }, + { + "type": { + "value": "SetCameraAngle" + }, + "parameters": [ + "", + "=", + "55", + "", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraRotationY" + }, + "parameters": [ + "", + "=", + "22", + "", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraRotationX" + }, + "parameters": [ + "", + "=", + "35", + "", + "" + ] + } + ] + } + ] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "disabled": true, + "name": "", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "KeyFromTextReleased" + }, + "parameters": [ + "", + "\"Up\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "Scene3D::SetCameraRotationX" + }, + "parameters": [ + "", + "+", + "360 / 16", + "", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "KeyFromTextReleased" + }, + "parameters": [ + "", + "\"Down\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "Scene3D::SetCameraRotationX" + }, + "parameters": [ + "", + "+", + "360 / 16", + "", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "KeyFromTextReleased" + }, + "parameters": [ + "", + "\"PageUp\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "Scene3D::SetCameraRotationY" + }, + "parameters": [ + "", + "+", + "360 / 16", + "", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "KeyFromTextReleased" + }, + "parameters": [ + "", + "\"PageDown\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "Scene3D::SetCameraRotationY" + }, + "parameters": [ + "", + "-", + "360 / 16", + "", + "" + ] + } + ] + } + ], + "parameters": [] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "PhysicsAirplane3D::PhysicsAirplane3D::SimulateAcceleratorKey" + }, + "parameters": [ + "Spaceship", + "PhysicsAirplane3D", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "KeyFromTextPressed" + }, + "parameters": [ + "", + "\"Up\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PhysicsAirplane3D::PhysicsAirplane3D::SimulateTurnUpKey" + }, + "parameters": [ + "Spaceship", + "PhysicsAirplane3D", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "KeyFromTextPressed" + }, + "parameters": [ + "", + "\"Down\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PhysicsAirplane3D::PhysicsAirplane3D::SimulateTurnDownKey" + }, + "parameters": [ + "Spaceship", + "PhysicsAirplane3D", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "KeyFromTextPressed" + }, + "parameters": [ + "", + "\"Right\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PhysicsAirplane3D::PhysicsAirplane3D::SimulateTurnRightKey" + }, + "parameters": [ + "Spaceship", + "PhysicsAirplane3D", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "KeyFromTextPressed" + }, + "parameters": [ + "", + "\"Left\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PhysicsAirplane3D::PhysicsAirplane3D::SimulateTurnLeftKey" + }, + "parameters": [ + "Spaceship", + "PhysicsAirplane3D", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::StickForce" + }, + "parameters": [ + "", + "!=", + "0", + "1", + "\"Left\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "PhysicsAirplane3D::PhysicsAirplane3D::SimulateTurnHorizontallyStick" + }, + "parameters": [ + "Spaceship", + "PhysicsAirplane3D", + "Gamepads::StickForceX(0, \"Left\")", + "" + ] + }, + { + "type": { + "value": "PhysicsAirplane3D::PhysicsAirplane3D::SimulateTurnVerticallyStick" + }, + "parameters": [ + "Spaceship", + "PhysicsAirplane3D", + "Gamepads::StickForceY(0, \"Left\")", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Raycaster3D::RaycastBetweenPosition" + }, + "parameters": [ + "", + "Obstacle", + "Spaceship.X()", + "Spaceship.Y()", + "Spaceship.Object3D::Z()", + "Spaceship.X() + 10000 * Spaceship.PhysicsAirplane3D::ForwardX()", + "Spaceship.Y() + 10000 * Spaceship.PhysicsAirplane3D::ForwardY()", + "Spaceship.Object3D::Z() + 10000 * Spaceship.PhysicsAirplane3D::ForwardZ()", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ProjectToCamera3D::MoveToProjectedPoint" + }, + "parameters": [ + "", + "Marker", + "", + "Raycaster3D::IntersectionX()", + "Raycaster3D::IntersectionY()", + "Raycaster3D::IntersectionZ()", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "RepeatEveryXSeconds::Repeat" + }, + "parameters": [ + "", + "\"Firing\"", + "0.125", + "" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "KeyFromTextPressed" + }, + "parameters": [ + "", + "\"LShift\"" + ] + }, + { + "type": { + "value": "Gamepads::C_Button_pressed" + }, + "parameters": [ + "", + "1", + "\"A\"", + "" + ] + } + ] + } + ], + "actions": [ + { + "type": { + "value": "Create" + }, + "parameters": [ + "", + "YellowSpark", + "Raycaster3D::IntersectionX()", + "Raycaster3D::IntersectionY()", + "" + ] + }, + { + "type": { + "value": "Create" + }, + "parameters": [ + "", + "RedSpark", + "Raycaster3D::IntersectionX()", + "Raycaster3D::IntersectionY()", + "" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetZ" + }, + "parameters": [ + "Spark", + "Object3D", + "=", + "Raycaster3D::IntersectionZ()" + ] + }, + { + "type": { + "value": "Collision3D::LookAtPosition" + }, + "parameters": [ + "", + "Spark", + "Object3D", + "Spark.X() + Raycaster3D::NormalX()", + "Spark.Y() + Raycaster3D::NormalY()", + "Spark.Object3D::Z() + Raycaster3D::NormalZ()", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Distance", + "=", + "Collision3D::Distance(Spaceship, Spark)" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::ApplyImpulse" + }, + "parameters": [ + "DynamicObstacle", + "Physics3D", + "0.0004 * (Spark.X() - Spaceship.X()) / Distance", + "0.0004 * (Spark.Y() - Spaceship.Y()) / Distance", + "0.0004 * (Spark.Object3D::Z() - Spaceship.Object3D::Z()) / Distance", + "Raycaster3D::IntersectionX()", + "Raycaster3D::IntersectionY()", + "Raycaster3D::IntersectionZ()" + ] + } + ], + "events": [ + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "DebuggerTools::ConsoleLog" + }, + "parameters": [ + "\"Distance: \" + Distance", + "\"info\"", + "" + ] + } + ] + } + ], + "variables": [ + { + "name": "Distance", + "type": "number", + "value": 0 + } + ] + }, + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "DebuggerTools::ConsoleLog" + }, + "parameters": [ + "ToString(Raycaster3D::NormalX()) + \" \" + ToString(Raycaster3D::NormalY()) + \" \" + ToString(Raycaster3D::NormalZ())", + "\"info\"", + "" + ] + } + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Avoid the spaceship spin from changing the camera target." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ThirdPersonCamera::ThirdPersonCamera::SetOffsetX" + }, + "parameters": [ + "Spaceship", + "ThirdPersonCamera", + "=", + "XFromAngleAndDistance(90 + Spaceship.PhysicsAirplane3D::CurrentSpin(), 4)", + "" + ] + }, + { + "type": { + "value": "ThirdPersonCamera::ThirdPersonCamera::SetOffsetZ" + }, + "parameters": [ + "Spaceship", + "ThirdPersonCamera", + "=", + "YFromAngleAndDistance(90 + Spaceship.PhysicsAirplane3D::CurrentSpin(), 4)", + "" + ] + }, + { + "type": { + "value": "ThirdPersonCamera::ThirdPersonCamera::MoveCameraCloser" + }, + "parameters": [ + "Spaceship", + "ThirdPersonCamera", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "KeyFromTextReleased" + }, + "parameters": [ + "", + "\"x\"" + ] + }, + { + "type": { + "value": "AjoutHasard" + }, + "parameters": [ + "", + "Cube" + ] + } + ], + "actions": [ + { + "type": { + "value": "Physics3D::Physics3DBehavior::ApplyImpulse" + }, + "parameters": [ + "Cube", + "Physics3D", + "0.0004", + "0", + "0", + "Cube.X()", + "Cube.Y()", + "Cube.Z()" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "KeyFromTextPressed" + }, + "parameters": [ + "", + "\"LControl\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::FireForwardObject3D" + }, + "parameters": [ + "Spaceship", + "FireBullet", + "Object3D", + "2", + "-3", + "-1", + "BottleKetchup", + "Object3D", + "Physics3D", + "300", + "" + ] + }, + { + "type": { + "value": "FireBullet::FireBullet::FireForwardObject3D" + }, + "parameters": [ + "Spaceship", + "FireBullet", + "Object3D", + "2", + "3", + "-1", + "BottleKetchup", + "Object3D", + "Physics3D", + "300", + "" + ] + } + ] + }, + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "KeyFromTextPressed" + }, + "parameters": [ + "", + "\"c\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::FireForwardCamera3D" + }, + "parameters": [ + "Spaceship", + "FireBullet", + "Object3D", + "20", + "-2", + "5", + "BottleKetchup", + "Object3D", + "Physics3D", + "0", + "" + ] + }, + { + "type": { + "value": "FireBullet::FireBullet::FireForwardCamera3D" + }, + "parameters": [ + "Spaceship", + "FireBullet", + "Object3D", + "20", + "2", + "5", + "BottleKetchup", + "Object3D", + "Physics3D", + "0", + "" + ] + } + ] + }, + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "KeyFromTextReleased" + }, + "parameters": [ + "", + "\"c\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::FireForwardCamera3D" + }, + "parameters": [ + "Spaceship", + "FireBullet", + "Object3D", + "20", + "0", + "0", + "Male_Casual", + "Object3D", + "Physics3D", + "0", + "" + ] + } + ] + } + ], + "layers": [ + { + "ambientLightColorB": 200, + "ambientLightColorG": 200, + "ambientLightColorR": 200, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "", + "renderingType": "", + "visibility": true, + "cameras": [ + { + "defaultSize": true, + "defaultViewport": true, + "height": 0, + "viewportBottom": 1, + "viewportLeft": 0, + "viewportRight": 1, + "viewportTop": 0, + "width": 0 + } + ], + "effects": [ + { + "effectType": "Scene3D::HemisphereLight", + "name": "3D Ambient Hemisphere Light", + "doubleParameters": { + "elevation": 40, + "intensity": 0.33, + "rotation": 60 + }, + "stringParameters": { + "groundColor": "127;127;127", + "skyColor": "255;255;255", + "top": "Z+" + }, + "booleanParameters": {} + }, + { + "effectType": "Scene3D::DirectionalLight", + "name": "3D Sun Light", + "doubleParameters": { + "distanceFromCamera": 1500, + "elevation": 40, + "frustumSize": 4000, + "intensity": 0.75, + "minimumShadowBias": 0, + "rotation": 60 + }, + "stringParameters": { + "color": "255;255;255", + "shadowQuality": "medium", + "top": "Z+" + }, + "booleanParameters": { + "isCastingShadow": true + } + }, + { + "effectType": "Scene3D::Skybox", + "name": "Skybox", + "doubleParameters": {}, + "stringParameters": { + "backFaceResourceName": "assets\\Cubemap_Sky_04-512x512_Back.png", + "bottomFaceResourceName": "assets\\Cubemap_Sky_04-512x512_Bottom.png", + "frontFaceResourceName": "assets\\Cubemap_Sky_04-512x512_Front.png", + "leftFaceResourceName": "assets\\Cubemap_Sky_04-512x512_Left.png", + "rightFaceResourceName": "assets\\Cubemap_Sky_04-512x512_Right.png", + "topFaceResourceName": "assets\\Cubemap_Sky_04-512x512_Top.png" + }, + "booleanParameters": {} + } + ] + }, + { + "ambientLightColorB": 200, + "ambientLightColorG": 200, + "ambientLightColorR": 200, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "UI", + "renderingType": "", + "visibility": true, + "cameras": [], + "effects": [ + { + "effectType": "Scene3D::HemisphereLight", + "name": "3D Ambient Hemisphere Light", + "doubleParameters": { + "elevation": 40, + "intensity": 0.33, + "rotation": 300 + }, + "stringParameters": { + "groundColor": "127;127;127", + "skyColor": "255;255;255", + "top": "Z+" + }, + "booleanParameters": {} + }, + { + "effectType": "Scene3D::DirectionalLight", + "name": "3D Sun Light", + "doubleParameters": { + "distanceFromCamera": 1500, + "elevation": 40, + "frustumSize": 4000, + "intensity": 0.75, + "minimumShadowBias": 0, + "rotation": 300 + }, + "stringParameters": { + "color": "255;255;255", + "shadowQuality": "medium", + "top": "Z+" + }, + "booleanParameters": { + "isCastingShadow": true + } + } + ] + } + ], + "behaviorsSharedData": [ + { + "name": "Animation", + "type": "AnimatableCapability::AnimatableBehavior" + }, + { + "name": "Effect", + "type": "EffectCapability::EffectBehavior" + }, + { + "name": "FireBullet", + "type": "FireBullet::FireBullet" + }, + { + "name": "Flippable", + "type": "FlippableCapability::FlippableBehavior" + }, + { + "name": "Object3D", + "type": "Scene3D::Base3DBehavior" + }, + { + "name": "Opacity", + "type": "OpacityCapability::OpacityBehavior" + }, + { + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "gravityX": 0, + "gravityY": 0, + "gravityZ": -9.8, + "worldScale": 100 + }, + { + "name": "PhysicsAirplane3D", + "type": "PhysicsAirplane3D::PhysicsAirplane3D" + }, + { + "name": "Resizable", + "type": "ResizableCapability::ResizableBehavior" + }, + { + "name": "Scale", + "type": "ScalableCapability::ScalableBehavior" + }, + { + "name": "ThirdPersonCamera", + "type": "ThirdPersonCamera::ThirdPersonCamera" + } + ] + } + ], + "externalEvents": [], + "eventsFunctionsExtensions": [ + { + "author": "", + "category": "Movement", + "dimension": "", + "extensionNamespace": "", + "fullName": "3D physics airplane", + "gdevelopVersion": "", + "helpPath": "", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMy4wLjMsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iSWNvbnMiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMzIgMzIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDMyIDMyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9DQoJLnN0MXtmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjI7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1taXRlcmxpbWl0OjEwO30NCjwvc3R5bGU+DQo8cG9seWdvbiBjbGFzcz0ic3QwIiBwb2ludHM9IjEzLDE4IDIxLDE4IDEyLDI4IDgsMjggIi8+DQo8cG9seWxpbmUgY2xhc3M9InN0MCIgcG9pbnRzPSIyMC4yLDE0IDEzLDYgOSw2IDEzLDE0ICIvPg0KPHBhdGggY2xhc3M9InN0MCIgZD0iTTEyLDIwSDRMMSw5aDNsNCw1SDI4YzAuOCwwLDEuNiwwLjMsMi4xLDAuOWwwLDBjMS4yLDEuMiwxLjIsMy4xLDAsNC4ybDAsMEMyOS41LDE5LjcsMjguOCwyMCwyOCwyMGgtOC44Ii8+DQo8L3N2Zz4NCg==", + "name": "PhysicsAirplane3D", + "previewIconUrl": "https://asset-resources.gdevelop.io/public-resources/Icons/Line Hero Pack/Master/SVG/Vehicles and Transport/49e91b8e69b677706be23ab4f1ca25d6771c0312e5f77dc1d93f95e7afa396b0_Vehicles and Transport_airplane_air_plane_fly.svg", + "shortDescription": "", + "version": "1.0.0", + "description": "", + "tags": [ + "3d" + ], + "authorIds": [ + "IWykYNRvhCZBN3vEgKEbBPOR3Oc2" + ], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [], + "eventsFunctions": [ + { + "description": "Define helper classes JavaScript code.", + "fullName": "Define helper classes", + "functionType": "Action", + "name": "DefineHelperClasses", + "private": true, + "sentence": "Define helper classes JavaScript code", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "if (gdjs.__physicsAirplane3DExtension) {", + " return;", + "}", + "", + "const rotationMatrix = new THREE.Matrix4();", + "", + "class ObjectLocalBasis {", + " /** @type {gdjs.RuntimeObject} */", + " object;", + " forward = new THREE.Vector3();", + "", + " /**", + " * @param object {gdjs.RuntimeObject}", + " */", + " constructor(object) {", + " this.object = object;", + " }", + "", + " update() {", + " const threeObject = this.object.get3DRendererObject();", + " rotationMatrix.makeRotationFromEuler(threeObject.rotation);", + " const elements = rotationMatrix.elements;", + " this.forward.set(", + " elements[0],", + " elements[1],", + " elements[2]", + " );", + " this.forward.normalize();", + " }", + "}", + "", + "gdjs.__physicsAirplane3DExtension = {", + " ObjectLocalBasis", + "};", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "DefineHelperClasses" + } + ] + }, + "eventsBasedBehaviors": [ + { + "description": "", + "fullName": "3D physics airplane", + "helpPath": "", + "iconUrl": "", + "name": "PhysicsAirplane3D", + "objectType": "", + "previewIconUrl": "", + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onCreated", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "PhysicsAirplane3D::DefineHelperClasses" + }, + "parameters": [ + "", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const { ObjectLocalBasis } = gdjs.__physicsAirplane3DExtension;\r", + "const object = objects[0];\r", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));\r", + "behavior.__physicsAirplane3DExtension = {\r", + " localBasis: new ObjectLocalBasis(object)\r", + "};" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CurrentForwardSpeed", + "=", + "ForwardSpeedMax" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "doStepPreEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TimeDelta", + "=", + "TimeDelta() * LayerTimeScale(Object.Layer())" + ] + } + ], + "events": [ + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Move", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "AcceleratorInput", + "!=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CurrentForwardSpeed", + "=", + "clamp(CurrentForwardSpeed + AcceleratorInput * ForwardAcceleration * TimeDelta, ForwardSpeedMin, ForwardSpeedMax)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "AcceleratorInput", + "=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CurrentForwardSpeed", + "=", + "clamp(CurrentForwardSpeed - ForwardDeceleration * TimeDelta, ForwardSpeedMin, ForwardSpeedMax)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "The splin animation is reverted for the movement calculus because it affect how the plane turn around its local Y and Z axis." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "PhysicsAirplane3D::PhysicsAirplane3D::TurnX" + }, + "parameters": [ + "Object", + "Behavior", + "-CurrentSpin", + "" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CurrentHorizontalAngularSpeed", + "=", + "TurnHorizontallyInput * HorizontalAngularSpeedMax" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CurrentVerticalAngularSpeed", + "=", + "TurnVerticallyInput * VerticalAngularSpeedMax" + ] + }, + { + "type": { + "value": "PhysicsAirplane3D::PhysicsAirplane3D::TurnZ" + }, + "parameters": [ + "Object", + "Behavior", + "CurrentHorizontalAngularSpeed * TimeDelta", + "" + ] + }, + { + "type": { + "value": "PhysicsAirplane3D::PhysicsAirplane3D::TurnY" + }, + "parameters": [ + "Object", + "Behavior", + "CurrentVerticalAngularSpeed * TimeDelta", + "" + ] + }, + { + "type": { + "value": "PhysicsAirplane3D::PhysicsAirplane3D::UpdateLocalBasis" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "Object", + "Physics3DBehavior", + "=", + "CurrentForwardSpeed * ForwardX" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "Object", + "Physics3DBehavior", + "=", + "CurrentForwardSpeed * ForwardY" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityZ" + }, + "parameters": [ + "Object", + "Physics3DBehavior", + "=", + "CurrentForwardSpeed * ForwardZ" + ] + }, + { + "type": { + "value": "PhysicsAirplane3D::PhysicsAirplane3D::TurnX" + }, + "parameters": [ + "Object", + "Behavior", + "CurrentSpin", + "" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Level back the wings", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentHorizontalAngularSpeed", + "=", + "0" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentVerticalAngularSpeed", + "=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "Scene3D::Base3DBehavior::SetRotationX" + }, + "parameters": [ + "Object", + "Object3D", + "=", + "AngleDifference(Object.Object3D::RotationX(), 0)" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "ForceFeedbackSpinSpeed", + "=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForceFeedbackSpinSpeed", + "=", + "abs(Object.Object3D::RotationX() / ForceFeedbackSpinDuration)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Scene3D::Base3DBehavior::RotationX" + }, + "parameters": [ + "Object", + "Object3D", + "<", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "Scene3D::Base3DBehavior::SetRotationX" + }, + "parameters": [ + "Object", + "Object3D", + "=", + "min(0, Object.Object3D::RotationX() + ForceFeedbackSpinSpeed * TimeDelta)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Scene3D::Base3DBehavior::RotationX" + }, + "parameters": [ + "Object", + "Object3D", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "Scene3D::Base3DBehavior::SetRotationX" + }, + "parameters": [ + "Object", + "Object3D", + "=", + "max(0, Object.Object3D::RotationX() - ForceFeedbackSpinSpeed * TimeDelta)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentSpin", + "<", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CurrentSpin", + "=", + "min(0, CurrentSpin + ForceFeedbackSpinSpeed * TimeDelta)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentSpin", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CurrentSpin", + "=", + "max(0, CurrentSpin - ForceFeedbackSpinSpeed * TimeDelta)" + ] + } + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Spin the wings to match rotation", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentHorizontalAngularSpeed", + "!=", + "0" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentVerticalAngularSpeed", + "!=", + "0" + ] + } + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForceFeedbackSpinSpeed", + "=", + "0" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentHorizontalAngularSpeed", + "<", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Delta", + "=", + "min(CurrentSpin + SpinSpeed * TimeDelta, SpinMax) - CurrentSpin" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentHorizontalAngularSpeed", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Delta", + "=", + "max(CurrentSpin - SpinSpeed * TimeDelta, -SpinMax) - CurrentSpin" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CurrentSpin", + "+", + "Delta" + ] + }, + { + "type": { + "value": "PhysicsAirplane3D::PhysicsAirplane3D::TurnX" + }, + "parameters": [ + "Object", + "Behavior", + "Delta", + "" + ] + } + ] + } + ], + "variables": [ + { + "name": "Delta", + "type": "number", + "value": 0 + } + ] + } + ] + } + ], + "parameters": [] + } + ], + "variables": [ + { + "name": "TimeDelta", + "type": "number", + "value": 0 + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TurnHorizontallyInput", + "=", + "0" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TurnVerticallyInput", + "=", + "0" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AcceleratorInput", + "=", + "0" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Turn the object around its local X axis.", + "fullName": "Turn around local X axis", + "functionType": "Action", + "name": "TurnX", + "private": true, + "sentence": "Turn _PARAM0_ of _PARAM2_° around its local X axis", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.RuntimeObject3D} */", + "const object = objects[0];", + "const angle = eventsFunctionContext.getArgument(\"Angle\");", + "", + "if (angle === 0) {", + " return;", + "}", + "const threeObject = object.get3DRendererObject();", + "threeObject.rotateX(gdjs.toRad(angle));", + "", + "const rotationX = gdjs.toDegrees(threeObject.rotation.x);", + "const rotationY = gdjs.toDegrees(threeObject.rotation.y);", + "const rotationZ = gdjs.toDegrees(threeObject.rotation.z);", + "// These methods overrides threeObject.rotation", + "object.setRotationX(rotationX);", + "object.setRotationY(rotationY);", + "object.setAngle(rotationZ);", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + }, + { + "description": "Angle (in degrees)", + "name": "Angle", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Turn the object around its local Y axis.", + "fullName": "Turn around local Y axis", + "functionType": "Action", + "name": "TurnY", + "private": true, + "sentence": "Turn _PARAM0_ of _PARAM2_° around its local Y axis", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.RuntimeObject3D} */", + "const object = objects[0];", + "const angle = eventsFunctionContext.getArgument(\"Angle\");", + "", + "if (angle === 0) {", + " return;", + "}", + "const threeObject = object.get3DRendererObject();", + "threeObject.rotateY(gdjs.toRad(angle));", + "", + "const rotationX = gdjs.toDegrees(threeObject.rotation.x);", + "const rotationY = gdjs.toDegrees(threeObject.rotation.y);", + "const rotationZ = gdjs.toDegrees(threeObject.rotation.z);", + "// These methods overrides threeObject.rotation", + "object.setRotationX(rotationX);", + "object.setRotationY(rotationY);", + "object.setAngle(rotationZ);", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + }, + { + "description": "Angle (in degrees)", + "name": "Angle", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Turn the object around its local Z axis.", + "fullName": "Turn around local Z axis", + "functionType": "Action", + "name": "TurnZ", + "private": true, + "sentence": "Turn _PARAM0_ of _PARAM2_° around its local Z axis", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.RuntimeObject3D} */", + "const object = objects[0];", + "const angle = eventsFunctionContext.getArgument(\"Angle\");", + "", + "console.log(angle);", + "if (angle === 0) {", + " return;", + "}", + "const threeObject = object.get3DRendererObject();", + "threeObject.rotateZ(gdjs.toRad(angle));", + "", + "const rotationX = gdjs.toDegrees(threeObject.rotation.x);", + "const rotationY = gdjs.toDegrees(threeObject.rotation.y);", + "const rotationZ = gdjs.toDegrees(threeObject.rotation.z);", + "// These methods overrides threeObject.rotation", + "object.setRotationX(rotationX);", + "object.setRotationY(rotationY);", + "object.setAngle(rotationZ);", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + }, + { + "description": "Angle (in degrees)", + "name": "Angle", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "fullName": "Update local basis", + "functionType": "Action", + "name": "UpdateLocalBasis", + "private": true, + "sentence": "Update local basis of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "const { localBasis } = behavior.__physicsAirplane3DExtension;", + "localBasis.update();", + "behavior._setForwardX(localBasis.forward.x);", + "behavior._setForwardY(localBasis.forward.y);", + "behavior._setForwardZ(localBasis.forward.z);", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Simulate a press of the turn right key.", + "fullName": "Simulate turn right key press", + "functionType": "Action", + "group": "3D physics airplane state", + "name": "SimulateTurnRightKey", + "sentence": "Simulate pressing turn right key for _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TurnHorizontallyInput", + "=", + "1" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Simulate a press of the turn left key.", + "fullName": "Simulate turn left key press", + "functionType": "Action", + "group": "3D physics airplane state", + "name": "SimulateTurnLeftKey", + "sentence": "Simulate pressing turn left key for _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TurnHorizontallyInput", + "=", + "-1" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Simulate a press of the move up key.", + "fullName": "Simulate turn up key press", + "functionType": "Action", + "group": "3D physics airplane state", + "name": "SimulateTurnUpKey", + "sentence": "Simulate pressing turn up key for _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TurnVerticallyInput", + "=", + "1" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Simulate a press of the move down key.", + "fullName": "Simulate turn down key press", + "functionType": "Action", + "group": "3D physics airplane state", + "name": "SimulateTurnDownKey", + "sentence": "Simulate pressing turn down key for _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TurnVerticallyInput", + "=", + "-1" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Simulate a press of the accelerator key.", + "fullName": "Simulate accelerator key press", + "functionType": "Action", + "group": "3D physics airplane state", + "name": "SimulateAcceleratorKey", + "sentence": "Simulate pressing Accelerator key for _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AcceleratorInput", + "=", + "1" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Simulate an accelerator stick control.", + "fullName": "Simulate accelerator stick control", + "functionType": "Action", + "group": "3D physics airplane state", + "name": "SimulateAcceleratorStick", + "sentence": "Simulate an accelerator stick control for _PARAM0_ with a _PARAM2_ force", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AcceleratorInput", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + }, + { + "description": "Force (-1 to 1)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Simulate turn horizontally stick control.", + "fullName": "Simulate turn horizontally stick control", + "functionType": "Action", + "group": "3D physics airplane state", + "name": "SimulateTurnHorizontallyStick", + "sentence": "Simulate turn horizontally stick control for _PARAM0_ with a _PARAM2_ force", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TurnHorizontallyInput", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + }, + { + "description": "Force (-1 to 1)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Simulate turn vertically stick control.", + "fullName": "Simulate turn vertically stick control", + "functionType": "Action", + "group": "3D physics airplane state", + "name": "SimulateTurnVerticallyStick", + "sentence": "Simulate turn vertically stick control for _PARAM0_ with a _PARAM2_ force", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TurnVerticallyInput", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + }, + { + "description": "Force (-1 to 1)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the forward X of the object.", + "fullName": "Forward X", + "functionType": "ExpressionAndCondition", + "group": "3D physics airplane state", + "name": "ForwardX", + "sentence": "the forward X", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ForwardX" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the forward Y of the object.", + "fullName": "Forward Y", + "functionType": "ExpressionAndCondition", + "group": "3D physics airplane state", + "name": "ForwardY", + "sentence": "the forward Y", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ForwardY" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the forward Z of the object.", + "fullName": "Forward Z", + "functionType": "ExpressionAndCondition", + "group": "3D physics airplane state", + "name": "ForwardZ", + "sentence": "the forward Z", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ForwardZ" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the current spin of the object.", + "fullName": "Current spin", + "functionType": "ExpressionAndCondition", + "group": "3D physics airplane state", + "name": "CurrentSpin", + "sentence": "the current spin", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "CurrentSpin" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the current forward speed of the object.", + "fullName": "Current forward speed", + "functionType": "ExpressionAndCondition", + "group": "3D physics airplane configuration", + "name": "CurrentForwardSpeed", + "sentence": "the current forward speed", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "CurrentForwardSpeed" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "CurrentForwardSpeed", + "group": "3D physics airplane configuration", + "name": "SetCurrentForwardSpeed", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CurrentForwardSpeed", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the current horizontal angular speed of the object.", + "fullName": "Current horizontal angular speed", + "functionType": "ExpressionAndCondition", + "group": "3D physics airplane configuration", + "name": "CurrentHorizontalAngularSpeed", + "sentence": "the current horizontal angular speed", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "CurrentHorizontalAngularSpeed" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "CurrentHorizontalAngularSpeed", + "group": "3D physics airplane configuration", + "name": "SetCurrentHorizontalAngularSpeed", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CurrentHorizontalAngularSpeed", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the current vertical angular speed of the object.", + "fullName": "Current vertical angular speed", + "functionType": "ExpressionAndCondition", + "group": "3D physics airplane configuration", + "name": "CurrentVerticalAngularSpeed", + "sentence": "the current vertical angular speed", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "CurrentVerticalAngularSpeed" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "CurrentVerticalAngularSpeed", + "group": "3D physics airplane configuration", + "name": "SetCurrentVerticalAngularSpeed", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CurrentVerticalAngularSpeed", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "PhysicsAirplane3D::PhysicsAirplane3D", + "type": "behavior" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onCreated" + }, + { + "functionName": "doStepPreEvents" + }, + { + "functionName": "TurnX" + }, + { + "functionName": "TurnY" + }, + { + "functionName": "TurnZ" + }, + { + "functionName": "UpdateLocalBasis" + }, + { + "folderName": "3D physics airplane state", + "children": [ + { + "functionName": "SimulateTurnRightKey" + }, + { + "functionName": "SimulateTurnLeftKey" + }, + { + "functionName": "SimulateTurnUpKey" + }, + { + "functionName": "SimulateTurnDownKey" + }, + { + "functionName": "SimulateAcceleratorKey" + }, + { + "functionName": "SimulateAcceleratorStick" + }, + { + "functionName": "SimulateTurnHorizontallyStick" + }, + { + "functionName": "SimulateTurnVerticallyStick" + }, + { + "functionName": "ForwardX" + }, + { + "functionName": "ForwardY" + }, + { + "functionName": "ForwardZ" + }, + { + "functionName": "CurrentSpin" + } + ] + }, + { + "folderName": "3D physics airplane configuration", + "children": [ + { + "functionName": "CurrentForwardSpeed" + }, + { + "functionName": "SetCurrentForwardSpeed" + }, + { + "functionName": "CurrentHorizontalAngularSpeed" + }, + { + "functionName": "SetCurrentHorizontalAngularSpeed" + }, + { + "functionName": "CurrentVerticalAngularSpeed" + }, + { + "functionName": "SetCurrentVerticalAngularSpeed" + } + ] + } + ] + }, + "propertyDescriptors": [ + { + "value": "", + "type": "Behavior", + "label": "3D capability", + "extraInformation": [ + "Scene3D::Base3DBehavior" + ], + "choices": [], + "name": "Object3D" + }, + { + "value": "", + "type": "Behavior", + "label": "3D physics engine", + "extraInformation": [ + "Physics3D::Physics3DBehavior" + ], + "choices": [], + "name": "Physics3DBehavior" + }, + { + "value": "0", + "type": "Number", + "unit": "PixelSpeed", + "label": "Current forward speed", + "hidden": true, + "name": "CurrentForwardSpeed" + }, + { + "value": "0", + "type": "Number", + "unit": "AngularSpeed", + "label": "Current horizontal angular speed", + "hidden": true, + "name": "CurrentHorizontalAngularSpeed" + }, + { + "value": "45", + "type": "Number", + "unit": "AngularSpeed", + "label": "Horizontal max angular speed", + "name": "HorizontalAngularSpeedMax" + }, + { + "value": "0", + "type": "Number", + "unit": "AngularSpeed", + "label": "Current vertical angular speed", + "hidden": true, + "name": "CurrentVerticalAngularSpeed" + }, + { + "value": "45", + "type": "Number", + "unit": "AngularSpeed", + "label": "Vertical max angular speed", + "name": "VerticalAngularSpeedMax" + }, + { + "value": "20", + "type": "Number", + "unit": "PixelSpeed", + "label": "Forward max speed", + "name": "ForwardSpeedMax" + }, + { + "value": "10", + "type": "Number", + "unit": "PixelSpeed", + "label": "Forward min speed", + "name": "ForwardSpeedMin" + }, + { + "value": "10", + "type": "Number", + "unit": "PixelAcceleration", + "label": "Forward acceleration", + "name": "ForwardAcceleration" + }, + { + "value": "5", + "type": "Number", + "unit": "PixelAcceleration", + "label": "Forward deceleration", + "name": "ForwardDeceleration" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Forward X", + "hidden": true, + "name": "ForwardX" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Forward Y", + "hidden": true, + "name": "ForwardY" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Forward Z", + "hidden": true, + "name": "ForwardZ" + }, + { + "value": "0", + "type": "Number", + "unit": "PixelSpeed", + "label": "Force feedback spin speed", + "hidden": true, + "name": "ForceFeedbackSpinSpeed" + }, + { + "value": "0.5", + "type": "Number", + "unit": "PixelSpeed", + "label": "Force feedback spin duration", + "description": "Spin back to level with the horizon when direction inputs are released. Can be set to 0 to disable it.", + "hidden": true, + "name": "ForceFeedbackSpinDuration" + }, + { + "value": "0", + "type": "Number", + "unit": "DegreeAngle", + "label": "Current spin", + "hidden": true, + "name": "CurrentSpin" + }, + { + "value": "60", + "type": "Number", + "unit": "DegreeAngle", + "label": "Max spin", + "name": "SpinMax" + }, + { + "value": "120", + "type": "Number", + "unit": "AngularSpeed", + "label": "Spin speed", + "name": "SpinSpeed" + }, + { + "value": "0", + "type": "Number", + "unit": "Dimensionless", + "label": "", + "name": "AcceleratorInput" + }, + { + "value": "0", + "type": "Number", + "unit": "Dimensionless", + "label": "", + "name": "TurnHorizontallyInput" + }, + { + "value": "0", + "type": "Number", + "unit": "Dimensionless", + "label": "", + "name": "TurnVerticallyInput" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "Object3D" + }, + { + "propertyName": "Physics3DBehavior" + }, + { + "propertyName": "CurrentForwardSpeed" + }, + { + "propertyName": "CurrentHorizontalAngularSpeed" + }, + { + "propertyName": "HorizontalAngularSpeedMax" + }, + { + "propertyName": "CurrentVerticalAngularSpeed" + }, + { + "propertyName": "VerticalAngularSpeedMax" + }, + { + "propertyName": "ForwardSpeedMax" + }, + { + "propertyName": "ForwardSpeedMin" + }, + { + "propertyName": "ForwardAcceleration" + }, + { + "propertyName": "ForwardDeceleration" + }, + { + "propertyName": "ForwardX" + }, + { + "propertyName": "ForwardY" + }, + { + "propertyName": "ForwardZ" + }, + { + "propertyName": "ForceFeedbackSpinSpeed" + }, + { + "propertyName": "ForceFeedbackSpinDuration" + }, + { + "propertyName": "CurrentSpin" + }, + { + "propertyName": "SpinMax" + }, + { + "propertyName": "SpinSpeed" + }, + { + "propertyName": "AcceleratorInput" + }, + { + "propertyName": "TurnHorizontallyInput" + }, + { + "propertyName": "TurnVerticallyInput" + } + ] + } + } + ], + "eventsBasedObjects": [] + }, + { + "author": "", + "category": "Camera", + "dimension": "3D", + "extensionNamespace": "", + "fullName": "Third person camera", + "gdevelopVersion": ">=5.5.222", + "helpPath": "", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMy4wLjMsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iSWNvbnMiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMzIgMzIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDMyIDMyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9DQo8L3N0eWxlPg0KPHBvbHlnb24gY2xhc3M9InN0MCIgcG9pbnRzPSI3LDEwIDEsMTMgNywxNiAxMywxMyAiLz4NCjxwb2x5bGluZSBjbGFzcz0ic3QwIiBwb2ludHM9IjEsMTMgMSwyMCA3LDIzIDEzLDIwIDEzLDEzICIvPg0KPGxpbmUgY2xhc3M9InN0MCIgeDE9IjciIHkxPSIxNiIgeDI9IjciIHkyPSIyMyIvPg0KPGxpbmUgY2xhc3M9InN0MCIgeDE9IjMxIiB5MT0iMTYiIHgyPSIyMSIgeTI9IjgiLz4NCjxsaW5lIGNsYXNzPSJzdDAiIHgxPSIyMSIgeTE9IjI0IiB4Mj0iMzEiIHkyPSIxNiIvPg0KPHBhdGggY2xhc3M9InN0MCIgZD0iTTIyLjcsMjIuNkMyMCwyMS43LDE4LDE5LjEsMTgsMTZjMC0zLjEsMi01LjcsNC43LTYuNiIvPg0KPHBhdGggY2xhc3M9InN0MCIgZD0iTTE5LjgsMTEuM2MxLjQsMS4xLDIuMiwyLjgsMi4yLDQuN2MwLDEuOS0wLjksMy42LTIuMiw0LjciLz4NCjwvc3ZnPg0K", + "name": "ThirdPersonCamera", + "previewIconUrl": "https://asset-resources.gdevelop.io/public-resources/Icons/Line Hero Pack/Master/SVG/Virtual Reality/94e95d2c318e1f3dc7151a351024e13c574e1e44669c6696aa107d60230073f6_Virtual Reality_3d_vision_eye_vr.svg", + "shortDescription": "Third-person camera orbiting an object at configurable distance, elevation, and rotation.", + "version": "1.8.1", + "description": [ + "Move the camera to look at an object from a given distance with a rotation and an elevation angles.", + "", + "It can be useful for:", + "- 3D platformer games ([open the project online](https://editor.gdevelop.io/?project=example://3d-platformer))", + "- 3D racing games ([open the project online](https://editor.gdevelop.io/?project=example://3d-car-coin-hunt))", + "- Orbit camera controls ([open the project online](https://editor.gdevelop.io/?project=example://3d-tile-based-city-builder))", + "- Isometric-like point of view ([open the project online](https://editor.gdevelop.io/?project=example://3d-road-crosser))" + ], + "origin": { + "identifier": "ThirdPersonCamera", + "name": "gdevelop-extension-store" + }, + "tags": [ + "3d", + "camera" + ], + "authorIds": [ + "IWykYNRvhCZBN3vEgKEbBPOR3Oc2" + ], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [], + "eventsFunctions": [ + { + "description": "Define helper classes JavaScript code.", + "fullName": "Define helper classes", + "functionType": "Action", + "name": "DefineHelperClasses", + "private": true, + "sentence": "Define helper classes JavaScript code", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "//@ts-ignore", + "if (gdjs.__thirdPersonCameraExtension) {", + " //@ts-ignore", + " return;", + "}", + "", + "class CameraLocalBasis {", + " /** @type {gdjs.RuntimeObject} */", + " object;", + " rotationMatrix = new THREE.Matrix4();", + " forward = new THREE.Vector3();", + "", + " /**", + " * @param object {gdjs.RuntimeObject}", + " */", + " constructor(object) {", + " this.object = object;", + " }", + "", + " update() {", + " const layer = this.object.getInstanceContainer().getLayer(this.object.getLayer());", + " const threeCamera = layer.getRenderer().getThreeCamera();", + " this.rotationMatrix.makeRotationFromEuler(threeCamera.rotation);", + " const elements = this.rotationMatrix.elements;", + "", + " this.forward.set(-elements[8], elements[9], -elements[10]);", + " // Normalize them, just in case (they should generally be unit vectors).", + " this.forward.normalize();", + " }", + "}", + "", + "class ObjectLocalBasis {", + " /** @type {gdjs.RuntimeObject} */", + " object;", + " rotationMatrix = new THREE.Matrix4();", + " forward = new THREE.Vector3();", + " up = new THREE.Vector3();", + " right = new THREE.Vector3();", + "", + " /**", + " * @param object {gdjs.RuntimeObject}", + " */", + " constructor(object) {", + " this.object = object;", + " }", + "", + " update() {", + " const threeObject = this.object.get3DRendererObject();", + " this.rotationMatrix.makeRotationFromEuler(threeObject.rotation);", + " const elements = this.rotationMatrix.elements;", + "", + " this.up.set(elements[8], elements[9], elements[10]);", + " this.forward.set(elements[0], elements[1], elements[2]);", + " this.right.crossVectors(this.forward, this.up);", + "", + " // Normalize them, just in case (they should generally be unit vectors).", + " this.right.normalize();", + " this.up.normalize();", + " this.forward.normalize();", + " }", + "}", + "", + "/**", + " * It can be built the follow:", + " * ", + " * `objectDefaultRotation.setFromAxisAngle(new THREE.Vector3(0, 0, 1), -Math.PI/2);`", + " * ", + " * `objectDefaultRotation.multiply(new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), Math.PI/2));`", + " * ", + " */", + "const objectDefaultRotation = new THREE.Quaternion(0.5, -0.5, -0.5, 0.5);", + "const targetQuaternion = new THREE.Quaternion();", + "const yAxis = new THREE.Vector3(0, 1, 0);", + "const zAxis = new THREE.Vector3(0, 0, 1);", + "const quaternion = new THREE.Quaternion();", + "const objectRotation = new THREE.Euler();", + "", + "/**", + " * @param object {gdjs.RuntimeObject}", + " * @param ratio {number}", + " * @param elevationAngleOffset {number}", + " */", + "function slerpCamera(object, ratio, rotationAngleOffset, elevationAngleOffset) {", + " const layer = object.getInstanceContainer().getLayer(object.getLayer());", + " const threeCamera = layer.getRenderer().getThreeCamera();", + " const threeObject = object.get3DRendererObject();", + "", + " objectRotation.copy(threeObject.rotation);", + " objectRotation.z = -objectRotation.z;", + " objectRotation.x = -objectRotation.x;", + " targetQuaternion.setFromEuler(objectRotation);", + " targetQuaternion.multiply(quaternion.setFromAxisAngle(zAxis, -gdjs.toRad(rotationAngleOffset)));", + " targetQuaternion.multiply(quaternion.setFromAxisAngle(yAxis, gdjs.toRad(elevationAngleOffset)));", + " targetQuaternion.multiply(objectDefaultRotation);", + "", + " threeCamera.quaternion.slerp(targetQuaternion, ratio);", + "", + " // The layer angle takes over the 3D camera Z rotation.", + " layer.setCameraRotation(gdjs.toDegrees(-threeCamera.rotation.z));", + "}", + "", + "//@ts-ignore", + "gdjs.__thirdPersonCameraExtension = {", + " CameraLocalBasis,", + " ObjectLocalBasis,", + " slerpCamera,", + "};", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "Move the camera to look at a position from a distance.", + "fullName": "Look at a position from a distance (deprecated)", + "functionType": "Action", + "name": "LookFromDistanceAtPosition", + "private": true, + "sentence": "Move the camera of _PARAM6_ to look at _PARAM1_; _PARAM2_ from _PARAM3_ pixels with a rotation of _PARAM4_° and an elevation of _PARAM5_°", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetCameraCenterX" + }, + "parameters": [ + "", + "=", + "PositionX + Distance * cos(ToRad(RotationAngle + 90)) * cos(ToRad(ElevationAngle))", + "Layer", + "" + ] + }, + { + "type": { + "value": "SetCameraCenterY" + }, + "parameters": [ + "", + "=", + "PositionY + Distance * sin(ToRad(RotationAngle + 90)) * cos(ToRad(ElevationAngle))", + "Layer", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraZ" + }, + "parameters": [ + "", + "=", + "Distance * sin(ToRad(ElevationAngle))", + "Layer", + "" + ] + }, + { + "type": { + "value": "Scene3D::TurnCameraTowardPosition" + }, + "parameters": [ + "", + "PositionX", + "PositionY", + "0", + "Layer", + "", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Position on X axis", + "name": "PositionX", + "type": "expression" + }, + { + "description": "Position on Y axis", + "name": "PositionY", + "type": "expression" + }, + { + "description": "Distance", + "name": "Distance", + "type": "expression" + }, + { + "description": "Rotation angle (around Z axis)", + "name": "RotationAngle", + "type": "expression" + }, + { + "description": "Elevation angle (around Y axis)", + "name": "ElevationAngle", + "type": "expression" + }, + { + "description": "Layer", + "name": "Layer", + "type": "layer" + } + ], + "objectGroups": [] + }, + { + "description": "Move the camera to look at an object from a distance.", + "fullName": "Look at an object from a distance (deprecated)", + "functionType": "Action", + "name": "LookFromDistanceAtObject", + "private": true, + "sentence": "Move the camera of _PARAM5_ to look at _PARAM1_ from _PARAM2_ pixels with a rotation of _PARAM3_° and an elevation of _PARAM4_°", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ThirdPersonCamera::LookFromDistanceAtPosition" + }, + "parameters": [ + "", + "Object.CenterX()", + "Object.CenterY()", + "Distance", + "RotationAngle", + "ElevationAngle", + "Layer", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "objectList" + }, + { + "description": "Distance", + "name": "Distance", + "type": "expression" + }, + { + "description": "Rotation angle (around Z axis)", + "name": "RotationAngle", + "type": "expression" + }, + { + "description": "Elevation angle (around Y axis)", + "name": "ElevationAngle", + "type": "expression" + }, + { + "description": "Layer", + "name": "Layer", + "type": "layer" + } + ], + "objectGroups": [] + }, + { + "description": "Move the camera to look at a position from a distance.", + "fullName": "Look at a position from a distance", + "functionType": "Action", + "name": "LookFromDistanceAtPosition3D", + "sentence": "Move the camera of _PARAM7_ to look at _PARAM1_; _PARAM2_; _PARAM3_ from _PARAM4_ pixels with a rotation of _PARAM5_° and an elevation of _PARAM6_°", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetCameraCenterX" + }, + "parameters": [ + "", + "=", + "PositionX + Distance * cos(ToRad(RotationAngle + 90)) * cos(ToRad(ElevationAngle))", + "Layer", + "" + ] + }, + { + "type": { + "value": "SetCameraCenterY" + }, + "parameters": [ + "", + "=", + "PositionY + Distance * sin(ToRad(RotationAngle + 90)) * cos(ToRad(ElevationAngle))", + "Layer", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraZ" + }, + "parameters": [ + "", + "=", + "PositionZ + Distance * sin(ToRad(ElevationAngle))", + "Layer", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraRotationX" + }, + "parameters": [ + "", + "=", + "90 - ElevationAngle", + "Layer", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraRotationY" + }, + "parameters": [ + "", + "=", + "0", + "Layer", + "" + ] + }, + { + "type": { + "value": "SetCameraAngle" + }, + "parameters": [ + "", + "=", + "RotationAngle", + "Layer", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Position on X axis", + "name": "PositionX", + "type": "expression" + }, + { + "description": "Position on Y axis", + "name": "PositionY", + "type": "expression" + }, + { + "description": "Position on Z axis", + "name": "PositionZ", + "type": "expression" + }, + { + "description": "Distance", + "name": "Distance", + "type": "expression" + }, + { + "description": "Rotation angle (around Z axis)", + "name": "RotationAngle", + "type": "expression" + }, + { + "description": "Elevation angle (around Y axis)", + "name": "ElevationAngle", + "type": "expression" + }, + { + "description": "Layer", + "name": "Layer", + "type": "layer" + } + ], + "objectGroups": [] + }, + { + "description": "Move the camera to look at an object from a distance.", + "fullName": "Look at an object from a distance", + "functionType": "Action", + "group": "Layers and cameras", + "name": "LookFromDistanceAtObject3D", + "sentence": "Move the camera of _PARAM6_ to look at _PARAM1_ from _PARAM3_ pixels with a rotation of _PARAM4_° and an elevation of _PARAM5_°", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ThirdPersonCamera::LookFromDistanceAtPosition3D" + }, + "parameters": [ + "", + "Object.CenterX()", + "Object.CenterY()", + "Object.Object3D::CenterZ()", + "Distance", + "RotationAngle", + "ElevationAngle", + "Layer", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + }, + { + "description": "Distance", + "name": "Distance", + "type": "expression" + }, + { + "description": "Rotation angle (around Z axis)", + "name": "RotationAngle", + "type": "expression" + }, + { + "description": "Elevation angle (around Y axis)", + "name": "ElevationAngle", + "type": "expression" + }, + { + "description": "Layer", + "name": "Layer", + "type": "layer" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Expression", + "name": "RotatedX", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Cos", + "=", + "cos(ToRad(RotationAngle))" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Sin", + "=", + "sin(ToRad(RotationAngle))" + ] + }, + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Cos * X - Sin * Y" + ] + } + ], + "variables": [ + { + "folded": true, + "name": "Cos", + "type": "number", + "value": 0 + }, + { + "folded": true, + "name": "Sin", + "type": "number", + "value": 0 + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Rotation angle", + "name": "RotationAngle", + "supplementaryInformation": "Tank::Tank", + "type": "expression" + }, + { + "description": "", + "name": "X", + "type": "expression" + }, + { + "description": "", + "name": "Y", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Expression", + "name": "RotatedY", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Cos", + "=", + "cos(ToRad(RotationAngle))" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Sin", + "=", + "sin(ToRad(RotationAngle))" + ] + }, + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Sin * X + Cos * Y" + ] + } + ], + "variables": [ + { + "folded": true, + "name": "Cos", + "type": "number", + "value": 0 + }, + { + "folded": true, + "name": "Sin", + "type": "number", + "value": 0 + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Rotation angle", + "name": "RotationAngle", + "supplementaryInformation": "Tank::Tank", + "type": "expression" + }, + { + "description": "", + "name": "X", + "type": "expression" + }, + { + "description": "", + "name": "Y", + "type": "expression" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "DefineHelperClasses" + }, + { + "functionName": "LookFromDistanceAtPosition" + }, + { + "functionName": "LookFromDistanceAtObject" + }, + { + "functionName": "LookFromDistanceAtPosition3D" + }, + { + "folderName": "Layers and cameras", + "children": [ + { + "functionName": "LookFromDistanceAtObject3D" + } + ] + }, + { + "functionName": "RotatedX" + }, + { + "functionName": "RotatedY" + } + ] + }, + "eventsBasedBehaviors": [ + { + "description": "Smoothly follow an object at a distance.", + "fullName": "Third person camera", + "helpPath": "", + "iconUrl": "", + "name": "ThirdPersonCamera", + "objectType": "", + "previewIconUrl": "", + "quickCustomizationVisibility": "hidden", + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onCreated", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ThirdPersonCamera::DefineHelperClasses" + }, + "parameters": [ + "", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const { CameraLocalBasis, ObjectLocalBasis } = gdjs.__thirdPersonCameraExtension;\r", + "const object = objects[0];\r", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));\r", + "behavior.__thirdPersonCameraExtension = {\r", + " cameraLocalBasis: new CameraLocalBasis(object),\r", + " objectlocalBasis: new ObjectLocalBasis(object)\r", + "};" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Update private properties through setters to check their values and initialize state." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ThirdPersonCamera::ThirdPersonCamera::SetRotationHalfwayDuration" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "RotationHalfwayDuration", + "" + ] + }, + { + "type": { + "value": "ThirdPersonCamera::ThirdPersonCamera::SetElevationHalfwayDuration" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "ElevationHalfwayDuration", + "" + ] + }, + { + "type": { + "value": "ThirdPersonCamera::ThirdPersonCamera::SetTranslationZHalfwayDuration" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "TranslationZHalfwayDuration", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "doStepPreEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "HasJustBeenCreated", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "HasJustBeenCreated", + "False", + "" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraZ", + "=", + "Object.Object3D::CenterZ()" + ] + }, + { + "type": { + "value": "ThirdPersonCamera::ThirdPersonCamera::JumpToTargetedRotation" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanVariable" + }, + "parameters": [ + "IsCalledManually", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ThirdPersonCamera::ThirdPersonCamera::DoMoveCameraCloser" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Move the camera closer to the object. This action must be called after the object has moved for the frame.", + "fullName": "Move the camera closer", + "functionType": "Action", + "name": "MoveCameraCloser", + "sentence": "Move the camera closer to _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "The camera following is called with an action, the call from doStepPreEvents must be disabled to avoid to do it twice." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BehaviorActivated" + }, + "parameters": [ + "Object", + "Behavior" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsCalledManually", + "False", + "" + ] + }, + { + "type": { + "value": "ThirdPersonCamera::ThirdPersonCamera::DoMoveCameraCloser" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Move the camera closer to the object.", + "fullName": "Do move the camera closer", + "functionType": "Action", + "name": "DoMoveCameraCloser", + "private": true, + "sentence": "Do move the camera closer _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "At each frame, the camera must catchup the target by a given ratio (speed)\ncameraX(t) - targetX = (cameraX(t - 1) - targetX) * (1 - speed)\n\nThe frame rate must not impact on the catch-up speed, we don't want a speed in ratio per frame but a speed ratio per second, like this:\ncameraX(t) - targetX = (cameraX(t - 1s) - targetX) * (1 - speed)\n\nOk, but we still need to process each frame, we can use a exponent for this:\ncameraX(t) - targetX = (cameraX(t - timeDelta) - targetX) * (1 - speed)^timeDelta\ncameraX(t) = targetX + (cameraX(t - timeDelta) - targetX) * exp(timeDelta * ln((1 - speed)))\n\npow is probably more efficient than precalculated log if the speed is changed continuously but this might be rare enough." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "RotationMode", + "=", + "\"ZYX\"" + ] + }, + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsRotatingWithObject", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ThirdPersonCamera::ThirdPersonCamera::Slerp" + }, + "parameters": [ + "Object", + "Behavior", + "1 - exp(TimeDelta() * RotationLogSpeed)", + "RotationAngleOffset", + "ElevationAngleOffset", + "" + ] + }, + { + "type": { + "value": "ThirdPersonCamera::ThirdPersonCamera::UpdateLocalBasis" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "value": "ThirdPersonCamera::ThirdPersonCamera::MoveToObject" + }, + "parameters": [ + "Object", + "Behavior", + "OffsetX", + "OffsetY", + "OffsetZ", + "" + ] + }, + { + "type": { + "value": "SetCameraCenterX" + }, + "parameters": [ + "", + "-", + "Distance * ForwardX", + "Object.Layer()", + "" + ] + }, + { + "type": { + "value": "SetCameraCenterY" + }, + "parameters": [ + "", + "-", + "Distance * ForwardY", + "Object.Layer()", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraZ" + }, + "parameters": [ + "", + "-", + "Distance * ForwardZ", + "Object.Layer()", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "RotationMode", + "!=", + "\"ZYX\"" + ] + }, + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsRotatingWithObject", + "False", + "" + ] + } + ] + } + ], + "actions": [], + "events": [ + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Z translation", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CameraZ", + "<", + "Object.Behavior::FreeAreaZMin()" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraZ", + "=", + "Object.Behavior::FreeAreaZMin() + (CameraZ - Object.Behavior::FreeAreaZMin()) * exp(TimeDelta() * TranslationZLogSpeed)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CameraZ", + ">", + "Object.Behavior::FreeAreaZMax()" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraZ", + "=", + "Object.Behavior::FreeAreaZMax() + (CameraZ - Object.Behavior::FreeAreaZMax()) * exp(TimeDelta() * TranslationZLogSpeed)" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Z rotation", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsRotatingWithObject", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetedRotationAngle", + "=", + "Object.Angle()" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "RotationMode", + "!=", + "\"Z\"" + ] + }, + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsElevatingWithObject", + "True", + "" + ] + } + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetedElevationAngle", + "=", + "Object.Object3D::RotationY()" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraRotationAngle", + "=", + "TargetedRotationAngle + 90 + RotationAngleOffset + AngleDifference(CameraAngle(Object.Layer()), TargetedRotationAngle + 90 + RotationAngleOffset) * exp(TimeDelta() * RotationLogSpeed)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraElevationAngle", + "=", + "TargetedElevationAngle + ElevationAngleOffset + AngleDifference(90 - Scene3D::CameraRotationX(Object.Layer()), TargetedElevationAngle + ElevationAngleOffset) * exp(TimeDelta() * ElevationLogSpeed)" + ] + }, + { + "type": { + "value": "ThirdPersonCamera::LookFromDistanceAtPosition3D" + }, + "parameters": [ + "", + "Object.CenterX() + ThirdPersonCamera::RotatedX(CameraRotationAngle, OffsetX, -OffsetY)", + "Object.CenterY() + ThirdPersonCamera::RotatedY(CameraRotationAngle, OffsetX, -OffsetY)", + "CameraZ + OffsetZ", + "Distance", + "CameraRotationAngle", + "CameraElevationAngle", + "Object.Layer()", + "" + ] + } + ], + "variables": [ + { + "folded": true, + "name": "CameraRotationAngle", + "type": "number", + "value": 0 + }, + { + "name": "CameraElevationAngle", + "type": "number", + "value": 0 + } + ] + } + ], + "parameters": [] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "Lerp camera", + "functionType": "Action", + "name": "Slerp", + "private": true, + "sentence": "Lerp the camera rotation to _PARAM0_ with a ratio of _PARAM2_ with rotation offset _PARAM3_° and elevation offset _PARAM4_°", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.RuntimeObject3D} */", + "const object = objects[0];", + "const ratio = eventsFunctionContext.getArgument(\"Ratio\");", + "const rotationAngleOffset = eventsFunctionContext.getArgument(\"NewRotationAngleOffset\");", + "const elevationAngleOffset = eventsFunctionContext.getArgument(\"NewElevationAngleOffset\");", + "", + "gdjs.__thirdPersonCameraExtension.slerpCamera(object, ratio, rotationAngleOffset, elevationAngleOffset);", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + }, + { + "description": "Ratio", + "name": "Ratio", + "type": "expression" + }, + { + "description": "Rotation angle offset", + "name": "NewRotationAngleOffset", + "type": "expression" + }, + { + "description": "Elevation angle offset", + "name": "NewElevationAngleOffset", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "fullName": "Move to object", + "functionType": "Action", + "name": "MoveToObject", + "private": true, + "sentence": "Change the camera position to _PARAM0_ with offset _PARAM2_, _PARAM3_, _PARAM4_ ", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.RuntimeObject3D} */", + "const object = objects[0];", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "const localOffsetX = eventsFunctionContext.getArgument(\"LocalOffsetX\");", + "const localOffsetY = eventsFunctionContext.getArgument(\"LocalOffsetY\");", + "const localOffsetZ = eventsFunctionContext.getArgument(\"LocalOffsetZ\");", + "", + "const layer = object.getInstanceContainer().getLayer(object.getLayer());", + "", + "const { objectlocalBasis } = behavior.__thirdPersonCameraExtension;", + "/** @type {{forward: THREE.Vector3, up: THREE.Vector3, right: THREE.Vector3 }} */", + "const { forward, up, right } = objectlocalBasis;", + "", + "layer.setCameraX(object.getCenterXInScene() + localOffsetX * right.x + localOffsetY * forward.x + localOffsetZ * up.x);", + "layer.setCameraY(object.getCenterYInScene() + localOffsetX * right.y + localOffsetY * forward.y + localOffsetZ * up.y);", + "layer.setCameraZ(object.getCenterZInScene() + localOffsetX * right.z + localOffsetY * forward.z + localOffsetZ * up.z);", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + }, + { + "description": "X offset", + "name": "LocalOffsetX", + "type": "expression" + }, + { + "description": "Y offset", + "name": "LocalOffsetY", + "type": "expression" + }, + { + "description": "Z offset", + "name": "LocalOffsetZ", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "fullName": "Update local basis", + "functionType": "Action", + "name": "UpdateLocalBasis", + "private": true, + "sentence": "Update local basis of _PARAM0_ and the camera", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "const { cameraLocalBasis, objectlocalBasis } = behavior.__thirdPersonCameraExtension;", + "cameraLocalBasis.update();", + "objectlocalBasis.update();", + "behavior._setForwardX(cameraLocalBasis.forward.x);", + "behavior._setForwardY(cameraLocalBasis.forward.y);", + "behavior._setForwardZ(cameraLocalBasis.forward.z);", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Rotate the camera all the way to the targeted angle.", + "fullName": "Rotate the camera all the way", + "functionType": "Action", + "name": "JumpToTargetedRotation", + "sentence": "Rotate the camera all the way to the targeted angle of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsRotatingWithObject", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetedRotationAngle", + "=", + "Object.Angle()" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsElevatingWithObject", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetedElevationAngle", + "=", + "Object.Object3D::RotationY()" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraAngle", + "=", + "TargetedRotationAngle + 90 + RotationAngleOffset" + ] + }, + { + "type": { + "value": "ThirdPersonCamera::LookFromDistanceAtPosition3D" + }, + "parameters": [ + "", + "Object.CenterX() + ThirdPersonCamera::RotatedX(CameraAngle, OffsetX, -OffsetY)", + "Object.CenterY() + ThirdPersonCamera::RotatedY(CameraAngle, OffsetX, -OffsetY)", + "CameraZ + OffsetZ", + "Distance", + "CameraAngle", + "Object.Object3D::RotationY() + ElevationAngleOffset", + "", + "" + ] + } + ], + "variables": [ + { + "folded": true, + "name": "CameraAngle", + "type": "number", + "value": 0 + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the camera rotation.", + "fullName": "Camera rotation", + "functionType": "ExpressionAndCondition", + "name": "RotationAngle", + "private": true, + "sentence": "the camera rotation", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "CameraAngle(Object.Layer())" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Rotate the camera all the way to the targeted angle.", + "fullName": "Rotate the camera all the way", + "functionType": "ActionWithOperator", + "getterName": "RotationAngle", + "name": "SetCameraRotation", + "sentence": "Rotate the camera all the way to the targeted angle of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ThirdPersonCamera::LookFromDistanceAtPosition3D" + }, + "parameters": [ + "", + "Object.CenterX() + ThirdPersonCamera::RotatedX(Value, OffsetX, -OffsetY)", + "Object.CenterY() + ThirdPersonCamera::RotatedY(Value, OffsetX, -OffsetY)", + "CameraZ + OffsetZ", + "Distance", + "Value", + "Object.Object3D::RotationY() + ElevationAngleOffset", + "", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the halfway time for rotation of the object.", + "fullName": "Halfway time for rotation", + "functionType": "ExpressionAndCondition", + "group": "Third person camera configuration", + "name": "RotationHalfwayDuration", + "sentence": "the halfway time for rotation", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "RotationHalfwayDuration" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "RotationHalfwayDuration", + "group": "Third person camera configuration", + "name": "SetRotationHalfwayDuration", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "ln((1 - speed)) = ln(1 / 2) / halfwatTime" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "RotationHalfwayDuration", + "=", + "Value" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "RotationLogSpeed", + "=", + "log(0.5) / Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the halfway time for elevation rotation of the object.", + "fullName": "Halfway time for elevation rotation", + "functionType": "ExpressionAndCondition", + "group": "Third person camera configuration", + "name": "ElevationHalfwayDuration", + "sentence": "the halfway time for elevation rotation", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ElevationHalfwayDuration" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "ElevationHalfwayDuration", + "group": "Third person camera configuration", + "name": "SetElevationHalfwayDuration", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "ln((1 - speed)) = ln(1 / 2) / halfwatTime" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ElevationHalfwayDuration", + "=", + "Value" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ElevationLogSpeed", + "=", + "log(0.5) / Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the halfway time on Z axis of the object.", + "fullName": "Halfway time on Z axis", + "functionType": "ExpressionAndCondition", + "group": "Third person camera configuration", + "name": "TranslationZHalfwayDuration", + "sentence": "the halfway time on Z axis", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "TranslationZHalfwayDuration" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "TranslationZHalfwayDuration", + "group": "Third person camera configuration", + "name": "SetTranslationZHalfwayDuration", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "ln((1 - speed)) = ln(1 / 2) / halfwatTime" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TranslationZHalfwayDuration", + "=", + "Value" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TranslationZLogSpeed", + "=", + "log(0.5) / Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Return follow free area bottom border Z.", + "fullName": "Free area Z min", + "functionType": "Expression", + "group": "Private", + "name": "FreeAreaZMin", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.Object3D::CenterZ() + OffsetZ - FollowFreeAreaZMin" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Return follow free area top border Z.", + "fullName": "Free area Z max", + "functionType": "Expression", + "group": "Private", + "name": "FreeAreaZMax", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.Object3D::CenterZ() + OffsetZ + FollowFreeAreaZMax" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the follow free area top border on Z axis of the object.", + "fullName": "Follow free area top border on Z axis", + "functionType": "ExpressionAndCondition", + "group": "Third person camera configuration", + "name": "FollowFreeAreaZMax", + "sentence": "the follow free area top border on Z axis", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "FollowFreeAreaZMax" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "FollowFreeAreaZMax", + "group": "Third person camera configuration", + "name": "SetFollowFreeAreaZMax", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "FollowFreeAreaZMax", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the follow free area bottom border on Z axis of the object.", + "fullName": "Follow free area bottom border on Z axis", + "functionType": "ExpressionAndCondition", + "group": "Third person camera configuration", + "name": "FollowFreeAreaZMin", + "sentence": "the follow free area bottom border on Z axis", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "FollowFreeAreaZMin" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "FollowFreeAreaZMin", + "group": "Third person camera configuration", + "name": "SetFollowFreeAreaZMin", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "FollowFreeAreaZMin", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the camera distance of the object.", + "fullName": "Camera distance", + "functionType": "ExpressionAndCondition", + "group": "Third person camera configuration", + "name": "Distance", + "sentence": "the camera distance", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Distance" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Distance", + "group": "Third person camera configuration", + "name": "SetDistance", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Distance", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the lateral distance offset of the object.", + "fullName": "Lateral distance offset", + "functionType": "ExpressionAndCondition", + "group": "Third person camera configuration", + "name": "OffsetX", + "sentence": "the lateral distance offset", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "OffsetX" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "OffsetX", + "group": "Third person camera configuration", + "name": "SetOffsetX", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "OffsetX", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the ahead distance offset of the object.", + "fullName": "Ahead distance offset", + "functionType": "ExpressionAndCondition", + "group": "Third person camera configuration", + "name": "OffsetY", + "sentence": "the ahead distance offset", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "OffsetY" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "OffsetY", + "group": "Third person camera configuration", + "name": "SetOffsetY", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "OffsetY", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the z offset of the object.", + "fullName": "Z offset", + "functionType": "ExpressionAndCondition", + "group": "Third person camera configuration", + "name": "OffsetZ", + "sentence": "the z offset", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "OffsetZ" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "OffsetZ", + "group": "Third person camera configuration", + "name": "SetOffsetZ", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "OffsetZ", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the rotation angle offset of the object.", + "fullName": "Rotation angle offset", + "functionType": "ExpressionAndCondition", + "group": "Third person camera configuration", + "name": "RotationAngleOffset", + "sentence": "the rotation angle offset", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "RotationAngleOffset" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "RotationAngleOffset", + "group": "Third person camera configuration", + "name": "SetRotationAngleOffset", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "RotationAngleOffset", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the elevation angle offset of the object.", + "fullName": "Elevation angle offset", + "functionType": "ExpressionAndCondition", + "group": "Third person camera configuration", + "name": "ElevationAngleOffset", + "sentence": "the elevation angle offset", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ElevationAngleOffset" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "ElevationAngleOffset", + "group": "Third person camera configuration", + "name": "SetElevationAngleOffset", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ElevationAngleOffset", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the targeted camera rotation angle of the object. When this angle is set, the camera follow this value instead of the object angle.", + "fullName": "Targeted rotation angle", + "functionType": "ExpressionAndCondition", + "group": "Third person camera configuration", + "name": "TargetedRotationAngle", + "sentence": "the targeted camera rotation angle", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "TargetedRotationAngle" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "TargetedRotationAngle", + "group": "Third person camera configuration", + "name": "SetTargetedRotationAngle", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TargetedRotationAngle", + "=", + "Value" + ] + }, + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsRotatingWithObject", + "False", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ThirdPersonCamera::ThirdPersonCamera", + "type": "behavior" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onCreated" + }, + { + "functionName": "doStepPreEvents" + }, + { + "functionName": "MoveCameraCloser" + }, + { + "functionName": "DoMoveCameraCloser" + }, + { + "functionName": "Slerp" + }, + { + "functionName": "MoveToObject" + }, + { + "functionName": "UpdateLocalBasis" + }, + { + "functionName": "JumpToTargetedRotation" + }, + { + "functionName": "RotationAngle" + }, + { + "functionName": "SetCameraRotation" + }, + { + "folderName": "Third person camera configuration", + "children": [ + { + "functionName": "RotationHalfwayDuration" + }, + { + "functionName": "SetRotationHalfwayDuration" + }, + { + "functionName": "ElevationHalfwayDuration" + }, + { + "functionName": "SetElevationHalfwayDuration" + }, + { + "functionName": "TranslationZHalfwayDuration" + }, + { + "functionName": "SetTranslationZHalfwayDuration" + }, + { + "functionName": "FollowFreeAreaZMax" + }, + { + "functionName": "SetFollowFreeAreaZMax" + }, + { + "functionName": "FollowFreeAreaZMin" + }, + { + "functionName": "SetFollowFreeAreaZMin" + }, + { + "functionName": "Distance" + }, + { + "functionName": "SetDistance" + }, + { + "functionName": "OffsetX" + }, + { + "functionName": "SetOffsetX" + }, + { + "functionName": "OffsetY" + }, + { + "functionName": "SetOffsetY" + }, + { + "functionName": "OffsetZ" + }, + { + "functionName": "SetOffsetZ" + }, + { + "functionName": "RotationAngleOffset" + }, + { + "functionName": "SetRotationAngleOffset" + }, + { + "functionName": "ElevationAngleOffset" + }, + { + "functionName": "SetElevationAngleOffset" + }, + { + "functionName": "TargetedRotationAngle" + }, + { + "functionName": "SetTargetedRotationAngle" + } + ] + }, + { + "folderName": "Private", + "children": [ + { + "functionName": "FreeAreaZMin" + }, + { + "functionName": "FreeAreaZMax" + } + ] + } + ] + }, + "propertyDescriptors": [ + { + "value": "", + "type": "Behavior", + "label": "3D capability", + "extraInformation": [ + "Scene3D::Base3DBehavior" + ], + "choices": [], + "name": "Object3D" + }, + { + "value": "0.125", + "type": "Number", + "unit": "Second", + "label": "Halfway time for rotation", + "group": "Catch-up speed", + "quickCustomizationVisibility": "hidden", + "name": "RotationHalfwayDuration" + }, + { + "value": "0", + "type": "Number", + "unit": "Second", + "label": "Halfway time for elevation rotation", + "description": "Only used by Z and ZY rotation modes", + "group": "Catch-up speed", + "quickCustomizationVisibility": "hidden", + "name": "ElevationHalfwayDuration" + }, + { + "value": "0.125", + "type": "Number", + "unit": "Second", + "label": "Halfway time on Z axis", + "description": "Only used by Z and ZY rotation modes", + "group": "Catch-up speed", + "quickCustomizationVisibility": "hidden", + "name": "TranslationZHalfwayDuration" + }, + { + "value": "500", + "type": "Number", + "unit": "Pixel", + "label": "Camera distance", + "group": "Position", + "name": "Distance" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Lateral distance offset", + "group": "Position", + "name": "OffsetX" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Ahead distance offset", + "group": "Position", + "name": "OffsetY" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Z offset", + "group": "Position", + "name": "OffsetZ" + }, + { + "value": "0", + "type": "Number", + "unit": "DegreeAngle", + "label": "Rotation angle offset", + "group": "Position", + "advanced": true, + "name": "RotationAngleOffset" + }, + { + "value": "20", + "type": "Number", + "unit": "DegreeAngle", + "label": "Elevation angle offset", + "group": "Position", + "name": "ElevationAngleOffset" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Follow free area top border on Z axis", + "group": "Position", + "advanced": true, + "quickCustomizationVisibility": "hidden", + "name": "FollowFreeAreaZMax" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Follow free area bottom border on Z axis", + "group": "Position", + "advanced": true, + "quickCustomizationVisibility": "hidden", + "name": "FollowFreeAreaZMin" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "RotationLogSpeed" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "ElevationLogSpeed" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "TranslationZLogSpeed" + }, + { + "value": "", + "type": "Boolean", + "label": "", + "hidden": true, + "name": "IsCalledManually" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "", + "hidden": true, + "name": "CameraZ" + }, + { + "value": "true", + "type": "Boolean", + "label": "", + "hidden": true, + "name": "HasJustBeenCreated" + }, + { + "value": "true", + "type": "Boolean", + "label": "Automatically rotate the camera with the object", + "quickCustomizationVisibility": "hidden", + "name": "IsRotatingWithObject" + }, + { + "value": "false", + "type": "Boolean", + "label": "Automatically rotate the camera with the object (elevation)", + "description": "Best left unchecked, use the rotation mode instead", + "deprecated": true, + "quickCustomizationVisibility": "hidden", + "name": "IsElevatingWithObject" + }, + { + "value": "Z", + "type": "Choice", + "label": "Rotation mode", + "choices": [ + { + "label": "Horizontal rotation (good for characters)", + "value": "Z" + }, + { + "label": "Vertical and horizontal rotations (good for cars)", + "value": "ZY" + }, + { + "label": "All rotations (good for spaceships)", + "value": "ZYX" + } + ], + "name": "RotationMode" + }, + { + "value": "0", + "type": "Number", + "unit": "DegreeAngle", + "label": "Targeted camera rotation angle", + "hidden": true, + "name": "TargetedRotationAngle" + }, + { + "value": "0", + "type": "Number", + "unit": "DegreeAngle", + "label": "Targeted camera rotation angle", + "hidden": true, + "name": "TargetedElevationAngle" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Forward X", + "hidden": true, + "name": "ForwardX" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Forward Y", + "hidden": true, + "name": "ForwardY" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Forward Z", + "hidden": true, + "name": "ForwardZ" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "Object3D" + }, + { + "folderName": "Catch-up speed", + "children": [ + { + "propertyName": "RotationHalfwayDuration" + }, + { + "propertyName": "ElevationHalfwayDuration" + }, + { + "propertyName": "TranslationZHalfwayDuration" + } + ] + }, + { + "folderName": "Position", + "children": [ + { + "propertyName": "Distance" + }, + { + "propertyName": "OffsetX" + }, + { + "propertyName": "OffsetY" + }, + { + "propertyName": "OffsetZ" + }, + { + "propertyName": "RotationAngleOffset" + }, + { + "propertyName": "ElevationAngleOffset" + }, + { + "propertyName": "FollowFreeAreaZMax" + }, + { + "propertyName": "FollowFreeAreaZMin" + } + ] + }, + { + "propertyName": "RotationLogSpeed" + }, + { + "propertyName": "ElevationLogSpeed" + }, + { + "propertyName": "TranslationZLogSpeed" + }, + { + "propertyName": "IsCalledManually" + }, + { + "propertyName": "CameraZ" + }, + { + "propertyName": "HasJustBeenCreated" + }, + { + "propertyName": "IsRotatingWithObject" + }, + { + "propertyName": "IsElevatingWithObject" + }, + { + "propertyName": "RotationMode" + }, + { + "propertyName": "TargetedRotationAngle" + }, + { + "propertyName": "TargetedElevationAngle" + }, + { + "propertyName": "ForwardX" + }, + { + "propertyName": "ForwardY" + }, + { + "propertyName": "ForwardZ" + } + ] + } + } + ], + "eventsBasedObjects": [] + }, + { + "author": "", + "category": "", + "dimension": "", + "extensionNamespace": "", + "fullName": "Convert 3D position to screen position", + "gdevelopVersion": "", + "helpPath": "", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMy4wLjMsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iSWNvbnMiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMzIgMzIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDMyIDMyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9DQo8L3N0eWxlPg0KPHBhdGggY2xhc3M9InN0MCIgZD0iTTI0LDEwLjljMCw3LTgsMTMuMS04LDEzLjFzLTgtNi4xLTgtMTMuMUM4LDYuNSwxMS42LDMsMTYsM1MyNCw2LjUsMjQsMTAuOXoiLz4NCjxjaXJjbGUgY2xhc3M9InN0MCIgY3g9IjE2IiBjeT0iMTEiIHI9IjIiLz4NCjxwb2x5bGluZSBjbGFzcz0ic3QwIiBwb2ludHM9IjE5LjIsMjEgMjUsMjEgMjksMjkgMywyOSA3LDIxIDEyLjgsMjEgIi8+DQo8L3N2Zz4NCg==", + "name": "ProjectToCamera3D", + "previewIconUrl": "https://asset-resources.gdevelop.io/public-resources/Icons/Line Hero Pack/Master/SVG/Maps and Navigation/5f308b28df69a05ce442f41f469dbeeae407726098ae481cbc58efb4f3514fe6_Maps and Navigation_location_pin_map.svg", + "shortDescription": "This extension provides functionality to convert 3D position to screen position.", + "version": "1.0.0", + "description": [ + "It can be useful to:", + "- Display a gun sights in a 3rd person view" + ], + "tags": [ + "3D" + ], + "authorIds": [ + "Zu55H5hcb9YmZTltIVOTAFDJQyB2", + "IWykYNRvhCZBN3vEgKEbBPOR3Oc2" + ], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [], + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onFirstSceneLoaded", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ProjectToCamera3D::DefineHelperClasses" + }, + "parameters": [ + "", + "" + ] + } + ] + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "Define helper classes JavaScript code.", + "fullName": "Define helper classes", + "functionType": "Action", + "name": "DefineHelperClasses", + "private": true, + "sentence": "Define helper classes JavaScript code", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "if (gdjs.__projectToCamera3DExtension) {", + " return;", + "}", + "", + "const vector = new THREE.Vector3();", + "const cameraDirection = new THREE.Vector3();", + "", + "/**", + " * @param {Array} objects", + " * @param {gdjs.RuntimeLayer} layer3D", + " * @param {float} x", + " * @param {float} y", + " * @param {float} z", + " */", + "function moveToProjectedPoint(objects, layer3D, x, y, z) {", + " const threeCamera = layer3D.getRenderer().getThreeCamera();", + "", + " const isPointBehindCamera = vector.set(x, -y, z).sub(threeCamera.position).dot(threeCamera.getWorldDirection(cameraDirection)) < 0;", + " if (isPointBehindCamera) {", + " for (const object of objects) {", + " object.setPosition(-10000, -10000);", + " }", + " return;", + " }", + "", + " const gameResolutionWidth = runtimeScene.getGame().getGameResolutionWidth();", + " const gameResolutionHeight = runtimeScene.getGame().getGameResolutionHeight();", + " vector.set(x, -y, z).project(threeCamera);", + " const projectedX = (gameResolutionWidth / 2) * (vector.x + 1);", + " const projectedY = (gameResolutionHeight / 2) * (1 - vector.y);", + "", + " for (const object of objects) {", + " object.setPosition(projectedX, projectedY);", + " }", + "", + "};", + "", + "gdjs.__projectToCamera3DExtension = {", + " moveToProjectedPoint", + "}", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "Change the 2D position of an object to make it overlaps the 3D position in a 3D layer.\nObjects must be on a 2D layer which is neither zoomed nor scrolled.", + "fullName": "Overlap a 3D point", + "functionType": "Action", + "group": "Position", + "name": "MoveToProjectedPoint", + "sentence": "Change the 2D position of _PARAM1_ to overlap _PARAM3_, _PARAM4_, _PARAM5_ from _PARAM2_ layer", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const layer3D = runtimeScene.getLayer(eventsFunctionContext.getArgument(\"Layer3D\"));", + "const x = eventsFunctionContext.getArgument(\"PositionX\");", + "const y = eventsFunctionContext.getArgument(\"PositionY\");", + "const z = eventsFunctionContext.getArgument(\"PositionZ\");", + "", + "gdjs.__projectToCamera3DExtension.moveToProjectedPoint(objects, layer3D, x, y, z);", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [] + } + ], + "parameters": [ + { + "description": "2D object", + "name": "Object", + "type": "objectList" + }, + { + "description": "3D layer", + "name": "Layer3D", + "type": "layer" + }, + { + "description": "X position", + "name": "PositionX", + "type": "expression" + }, + { + "description": "Y position", + "name": "PositionY", + "type": "expression" + }, + { + "description": "Z position", + "name": "PositionZ", + "type": "expression" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onFirstSceneLoaded" + }, + { + "functionName": "DefineHelperClasses" + }, + { + "folderName": "Position", + "children": [ + { + "functionName": "MoveToProjectedPoint" + } + ] + } + ] + }, + "eventsBasedBehaviors": [], + "eventsBasedObjects": [] + }, + { + "author": "", + "category": "General", + "dimension": "", + "extensionNamespace": "", + "fullName": "3D raycast", + "gdevelopVersion": ">=5.5.222", + "helpPath": "", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0ibWRpLXJheS1zdGFydC1hcnJvdyIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxwYXRoIGQ9Ik0yMywxMkwxOSwxNlYxM0g2LjgzQzYuNDIsMTQuMTcgNS4zMSwxNSA0LDE1QTMsMyAwIDAsMSAxLDEyQTMsMyAwIDAsMSA0LDlDNS4zMSw5IDYuNDIsOS44MyA2LjgzLDExSDE5VjhMMjMsMTJaIiAvPjwvc3ZnPg==", + "name": "Raycaster3D", + "previewIconUrl": "https://asset-resources.gdevelop.io/public-resources/Icons/8419f46b76bce482c14b4c03b4141a64d457e4cdc92686f3470381f5d2694abd_ray-start-arrow.svg", + "shortDescription": "Find 3D objects that cross a line.", + "version": "0.1.7", + "description": [ + "It can be useful to:", + "- Find 3D objects under the pointer", + "- Target objects from a 1st person view", + "- Make AI that detect objects in their field of view" + ], + "origin": { + "identifier": "Raycaster3D", + "name": "gdevelop-extension-store" + }, + "tags": [ + "3d", + "recast", + "collision" + ], + "authorIds": [ + "IWykYNRvhCZBN3vEgKEbBPOR3Oc2" + ], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [], + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onFirstSceneLoaded", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Raycaster3D::DefineHelperClasses" + }, + "parameters": [ + "", + "" + ] + } + ] + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "Define helper classes JavaScript code.", + "fullName": "Define helper classes", + "functionType": "Action", + "name": "DefineHelperClasses", + "private": true, + "sentence": "Define helper classes JavaScript code", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "if (gdjs.__raycaster3DExtension) {", + " return;", + "}", + "", + "class Raycaster {", + " raycaster = new THREE.Raycaster();", + " pointer = new THREE.Vector2();", + " /** @type {Array} */", + " raycastResults = [];", + " lastDistance = 0;", + " lastPositionX = 0;", + " lastPositionY = 0;", + " lastPositionZ = 0;", + " lastNormal = new THREE.Vector3();", + "", + " /**", + " * @param objectsLists {Hashtable}", + " * @param objects {gdjs.RuntimeObject[]}", + " * @param pointerX {number}", + " * @param pointerY {number}", + " * @param distanceMax {number}", + " */", + " recastFromCamera(objectsLists, objects, pointerX, pointerY, distanceMax) {", + " if (objects.length === 0) {", + " return false;", + " }", + " const object = objects[0];", + " const layer = object.getInstanceContainer().getLayer(object.getLayer());", + " const camera = layer.getRenderer().getThreeCamera();", + "", + " const raycaster = this.raycaster;", + " const pointer = this.pointer;", + " pointer.x = -1 + 2 * pointerX;", + " pointer.y = 1 - 2 * pointerY;", + " raycaster.setFromCamera(pointer, camera);", + " raycaster.far = distanceMax;", + "", + " return this._doRecast(objectsLists, objects);", + " }", + "", + " /**", + " * @param objectsLists {Hashtable}", + " * @param objects {gdjs.RuntimeObject[]}", + " * @param originX {number}", + " * @param originY {number}", + " * @param originZ {number}", + " * @param rotationAngle {number}", + " * @param elevationAngle {number}", + " * @param distanceMax {number}", + " */", + " recastWithAngle(", + " objectsLists,", + " objects,", + " originX,", + " originY,", + " originZ,", + " rotationAngle,", + " elevationAngle,", + " distanceMax", + " ) {", + " if (objects.length === 0) {", + " return false;", + " }", + " const raycaster = this.raycaster;", + " raycaster.ray.origin.set(", + " originX,", + " -originY,", + " originZ,", + " );", + " const rotation = rotationAngle * Math.PI / 180;", + " const elevation = elevationAngle * Math.PI / 180;", + " const cosElevation = Math.cos(elevation);", + " raycaster.ray.direction.set(", + " Math.cos(rotation) * cosElevation,", + " -Math.sin(rotation) * cosElevation,", + " Math.sin(elevation),", + " );", + " raycaster.far = distanceMax;", + "", + " return this._doRecast(objectsLists, objects);", + " }", + "", + " /**", + " * @param objectsLists {Hashtable}", + " * @param objects {gdjs.RuntimeObject[]}", + " * @param originX {number}", + " * @param originY {number}", + " * @param originZ {number}", + " * @param targetX {number}", + " * @param targetY {number}", + " * @param targetZ {number}", + " * @param distanceMax {number}", + " */", + " recastBetweenPosition(", + " objectsLists,", + " objects,", + " originX,", + " originY,", + " originZ,", + " targetX,", + " targetY,", + " targetZ", + " ) {", + " if (objects.length === 0) {", + " return false;", + " }", + " const raycaster = this.raycaster;", + " raycaster.ray.origin.set(", + " originX,", + " -originY,", + " originZ,", + " );", + " const deltaX = targetX - originX;", + " const deltaY = targetY - originY;", + " const deltaZ = targetZ - originZ;", + " const deltaLength = Math.hypot(deltaX, deltaY, deltaZ);", + " raycaster.ray.direction.set(", + " deltaX / deltaLength,", + " -deltaY / deltaLength,", + " deltaZ / deltaLength,", + " );", + " raycaster.far = deltaLength;", + "", + " return this._doRecast(objectsLists, objects);", + " }", + "", + " /**", + " * @param objectsLists {Hashtable}", + " * @param objects {gdjs.RuntimeObject[]}", + " */", + " _doRecast(objectsLists, objects) {", + " const raycastResults = this.raycastResults;", + " let distanceMin = Number.MAX_VALUE;", + " /** @type {gdjs.RuntimeObject | null} */", + " let nearestObject = null;", + " /** @type {THREE.Object3D | null} */", + " let nearestThreeObject = null;", + " for (const object of objects) {", + " raycastResults.length = 0;", + " const threeObject = object.get3DRendererObject();", + " if (!threeObject) {", + " continue;", + " }", + " this.raycaster.intersectObject(threeObject, true, raycastResults);", + " if (raycastResults.length > 0 && raycastResults[0].distance < distanceMin) {", + " const raycastResult = raycastResults[0];", + " distanceMin = raycastResult.distance;", + " nearestObject = object;", + " this.lastDistance = raycastResult.distance;", + " this.lastPositionX = raycastResult.point.x;", + " this.lastPositionY = -raycastResult.point.y;", + " this.lastPositionZ = raycastResult.point.z;", + " this.lastNormal.copy(raycastResult.normal);", + " nearestThreeObject = raycastResult.object;", + " }", + " }", + " if (!nearestObject) {", + " return false;", + " }", + " this.lastNormal.transformDirection(nearestThreeObject.matrixWorld);", + " this.lastNormal.y = -this.lastNormal.y;", + " raycastResults.length = 0;", + " gdjs.evtTools.object.pickOnly(", + " objectsLists,", + " nearestObject", + " );", + " return true;", + " }", + "}", + "", + "gdjs.__raycaster3DExtension = {", + " Raycaster,", + " raycaster: new Raycaster(),", + "}", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "Sends a ray from the given source position and angle, intersecting the closest object. The intersected object will become the only one taken into account.", + "fullName": "Raycast", + "functionType": "Condition", + "group": "Collision", + "name": "RaycastWithAngle", + "sentence": "Cast a ray from _PARAM2_; _PARAM3_; _PARAM4_ toward a rotation of _PARAM5_°, an elevation of _PARAM6_° and max distance of _PARAM7_ against _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "eventsFunctionContext.returnValue =", + " gdjs.__raycaster3DExtension.raycaster.recastWithAngle(", + " eventsFunctionContext.getObjectsLists(\"Object\"),", + " objects,", + " eventsFunctionContext.getArgument(\"OriginX\"),", + " eventsFunctionContext.getArgument(\"OriginY\"),", + " eventsFunctionContext.getArgument(\"OriginZ\"),", + " eventsFunctionContext.getArgument(\"RotationAngle\"),", + " eventsFunctionContext.getArgument(\"ElevationAngle\"),", + " eventsFunctionContext.getArgument(\"DistanceMax\")", + " );", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Objects to test against the ray", + "name": "Object", + "type": "objectList" + }, + { + "description": "Ray source X position", + "name": "OriginX", + "type": "expression" + }, + { + "description": "Ray source Y position", + "name": "OriginY", + "type": "expression" + }, + { + "description": "Ray source Z position", + "name": "OriginZ", + "type": "expression" + }, + { + "description": "Rotation angle (in degrees)", + "name": "RotationAngle", + "type": "expression" + }, + { + "description": "Elevation angle (in degrees)", + "name": "ElevationAngle", + "type": "expression" + }, + { + "description": "Ray maximum distance (in pixels)", + "name": "DistanceMax", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Sends a ray from the given source position to the final point, intersecting the closest object. The intersected object will become the only one taken into account.", + "fullName": "Raycast to a position", + "functionType": "Condition", + "group": "Collision", + "name": "RaycastBetweenPosition", + "sentence": "Cast a ray from _PARAM2_; _PARAM3_; _PARAM4_ to _PARAM5_; _PARAM6_; _PARAM7_ against _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "eventsFunctionContext.returnValue =", + " gdjs.__raycaster3DExtension.raycaster.recastBetweenPosition(", + " eventsFunctionContext.getObjectsLists(\"Object\"),", + " objects,", + " eventsFunctionContext.getArgument(\"OriginX\"),", + " eventsFunctionContext.getArgument(\"OriginY\"),", + " eventsFunctionContext.getArgument(\"OriginZ\"),", + " eventsFunctionContext.getArgument(\"TargetX\"),", + " eventsFunctionContext.getArgument(\"TargetY\"),", + " eventsFunctionContext.getArgument(\"TargetZ\")", + " );", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Objects to test against the ray", + "name": "Object", + "type": "objectList" + }, + { + "description": "Ray source X position", + "name": "OriginX", + "type": "expression" + }, + { + "description": "Ray source Y position", + "name": "OriginY", + "type": "expression" + }, + { + "description": "Ray source Z position", + "name": "OriginZ", + "type": "expression" + }, + { + "description": "Ray target X position", + "name": "TargetX", + "type": "expression" + }, + { + "description": "Ray target Y position", + "name": "TargetY", + "type": "expression" + }, + { + "description": "Ray target Z position", + "name": "TargetZ", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Sends a ray from the center of the camera, intersecting the closest object. The intersected object will become the only one taken into account.", + "fullName": "Raycast from camera center", + "functionType": "Condition", + "group": "Collision", + "name": "RaycastFromCameraCenter", + "sentence": "Cast a ray from the camera center to a maximum distance of _PARAM2_ against _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "eventsFunctionContext.returnValue =", + " gdjs.__raycaster3DExtension.raycaster.recastFromCamera(", + " eventsFunctionContext.getObjectsLists(\"Object\"),", + " objects,", + " 0.5,", + " 0.5,", + " eventsFunctionContext.getArgument(\"DistanceMax\")", + " );", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Objects to test against the ray", + "name": "Object", + "type": "objectList" + }, + { + "description": "Ray maximum distance (in pixels)", + "name": "DistanceMax", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Sends a ray from the given source point on the camera screen, intersecting the closest object. The intersected object will become the only one taken into account.", + "fullName": "Raycast from a camera point", + "functionType": "Condition", + "group": "Collision", + "name": "RaycastFromCameraPoint", + "sentence": "Cast a ray from the camera point _PARAM2_; _PARAM3_ to a maximum distance of _PARAM4_ against _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "eventsFunctionContext.returnValue =", + " gdjs.__raycaster3DExtension.raycaster.recastFromCamera(", + " eventsFunctionContext.getObjectsLists(\"Object\"),", + " objects,", + " eventsFunctionContext.getArgument(\"PointerX\"),", + " eventsFunctionContext.getArgument(\"PointerY\"),", + " eventsFunctionContext.getArgument(\"DistanceMax\")", + " );", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Objects to test against the ray", + "name": "Object", + "type": "objectList" + }, + { + "description": "X position on the screen (from 0 to 1)", + "name": "PointerX", + "type": "expression" + }, + { + "description": "Y position on the screen (from 0 to 1)", + "name": "PointerY", + "type": "expression" + }, + { + "description": "Ray maximum distance (in pixels)", + "name": "DistanceMax", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Sends a ray from the cursor on the camera screen, intersecting the closest object. The intersected object will become the only one taken into account.", + "fullName": "Raycast from cursor", + "functionType": "Condition", + "group": "Collision", + "name": "RaycastFromCameraCursor", + "sentence": "Cast a ray from the cursor on 2D layer: _PARAM2_ to a maximum distance of _PARAM3_ against _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const { camera, input } = gdjs.evtTools;", + "", + "const layer2D = eventsFunctionContext.getArgument(\"Layer2D\");", + "", + "const cameraMinX = camera.getCameraBorderLeft(runtimeScene, layer2D, 0);", + "const cameraMaxX = camera.getCameraBorderRight(runtimeScene, layer2D, 0);", + "const cameraMinY = camera.getCameraBorderTop(runtimeScene, layer2D, 0);", + "const cameraMaxY = camera.getCameraBorderBottom(runtimeScene, layer2D, 0);", + "", + "const cursorX = input.getCursorX(runtimeScene, layer2D, 0);", + "const cursorY = input.getCursorY(runtimeScene, layer2D, 0);", + "", + "eventsFunctionContext.returnValue =", + " gdjs.__raycaster3DExtension.raycaster.recastFromCamera(", + " eventsFunctionContext.getObjectsLists(\"Object\"),", + " objects,", + " (cursorX - cameraMinX) / (cameraMaxX - cameraMinX),", + " (cursorY - cameraMinY) / (cameraMaxY - cameraMinY),", + " eventsFunctionContext.getArgument(\"DistanceMax\")", + " );", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Objects to test against the ray", + "name": "Object", + "type": "objectList" + }, + { + "description": "2D layer", + "name": "Layer2D", + "type": "layer" + }, + { + "description": "Ray maximum distance (in pixels)", + "name": "DistanceMax", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the last recast intersection distance.", + "fullName": "Last recast distance", + "functionType": "ExpressionAndCondition", + "name": "Distance", + "sentence": "the last recast intersection distance", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": "eventsFunctionContext.returnValue = gdjs.__raycaster3DExtension.raycaster.lastDistance;", + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [], + "objectGroups": [] + }, + { + "description": "Return the last recast intersection position on X axis.", + "fullName": "Last recast X intersection", + "functionType": "Expression", + "name": "IntersectionX", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": "eventsFunctionContext.returnValue = gdjs.__raycaster3DExtension.raycaster.lastPositionX;", + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [], + "objectGroups": [] + }, + { + "description": "Return the last recast intersection position on Y axis.", + "fullName": "Last recast Y intersection", + "functionType": "Expression", + "name": "IntersectionY", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": "eventsFunctionContext.returnValue = gdjs.__raycaster3DExtension.raycaster.lastPositionY;", + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [], + "objectGroups": [] + }, + { + "description": "Return the last recast intersection position on Z axis.", + "fullName": "Last recast Z intersection", + "functionType": "Expression", + "name": "IntersectionZ", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": "eventsFunctionContext.returnValue = gdjs.__raycaster3DExtension.raycaster.lastPositionZ;", + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [], + "objectGroups": [] + }, + { + "description": "Return the last recast intersection normal on X axis.", + "fullName": "Last recast X normal", + "functionType": "Expression", + "name": "NormalX", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": "eventsFunctionContext.returnValue = gdjs.__raycaster3DExtension.raycaster.lastNormal.x;", + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [], + "objectGroups": [] + }, + { + "description": "Return the last recast intersection normal on X axis.", + "fullName": "Last recast X normal", + "functionType": "Expression", + "name": "NormalY", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": "eventsFunctionContext.returnValue = gdjs.__raycaster3DExtension.raycaster.lastNormal.y;", + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [], + "objectGroups": [] + }, + { + "description": "Return the last recast intersection normal on Z axis.", + "fullName": "Last recast Z normal", + "functionType": "Expression", + "name": "NormalZ", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": "eventsFunctionContext.returnValue = gdjs.__raycaster3DExtension.raycaster.lastNormal.z;", + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onFirstSceneLoaded" + }, + { + "functionName": "DefineHelperClasses" + }, + { + "folderName": "Collision", + "children": [ + { + "functionName": "RaycastWithAngle" + }, + { + "functionName": "RaycastBetweenPosition" + }, + { + "functionName": "RaycastFromCameraCenter" + }, + { + "functionName": "RaycastFromCameraPoint" + }, + { + "functionName": "RaycastFromCameraCursor" + } + ] + }, + { + "functionName": "Distance" + }, + { + "functionName": "IntersectionX" + }, + { + "functionName": "IntersectionY" + }, + { + "functionName": "IntersectionZ" + }, + { + "functionName": "NormalX" + }, + { + "functionName": "NormalY" + }, + { + "functionName": "NormalZ" + } + ] + }, + "eventsBasedBehaviors": [], + "eventsBasedObjects": [] + }, + { + "author": "", + "category": "Visual effect", + "dimension": "", + "extensionNamespace": "", + "fullName": "3D particle emitter", + "gdevelopVersion": ">=5.5.222", + "helpPath": "", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0ibWRpLWZpcmUiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTcuNjYgMTEuMkMxNy40MyAxMC45IDE3LjE1IDEwLjY0IDE2Ljg5IDEwLjM4QzE2LjIyIDkuNzggMTUuNDYgOS4zNSAxNC44MiA4LjcyQzEzLjMzIDcuMjYgMTMgNC44NSAxMy45NSAzQzEzIDMuMjMgMTIuMTcgMy43NSAxMS40NiA0LjMyQzguODcgNi40IDcuODUgMTAuMDcgOS4wNyAxMy4yMkM5LjExIDEzLjMyIDkuMTUgMTMuNDIgOS4xNSAxMy41NUM5LjE1IDEzLjc3IDkgMTMuOTcgOC44IDE0LjA1QzguNTcgMTQuMTUgOC4zMyAxNC4wOSA4LjE0IDEzLjkzQzguMDggMTMuODggOC4wNCAxMy44MyA4IDEzLjc2QzYuODcgMTIuMzMgNi42OSAxMC4yOCA3LjQ1IDguNjRDNS43OCAxMCA0Ljg3IDEyLjMgNSAxNC40N0M1LjA2IDE0Ljk3IDUuMTIgMTUuNDcgNS4yOSAxNS45N0M1LjQzIDE2LjU3IDUuNyAxNy4xNyA2IDE3LjdDNy4wOCAxOS40MyA4Ljk1IDIwLjY3IDEwLjk2IDIwLjkyQzEzLjEgMjEuMTkgMTUuMzkgMjAuOCAxNy4wMyAxOS4zMkMxOC44NiAxNy42NiAxOS41IDE1IDE4LjU2IDEyLjcyTDE4LjQzIDEyLjQ2QzE4LjIyIDEyIDE3LjY2IDExLjIgMTcuNjYgMTEuMk0xNC41IDE3LjVDMTQuMjIgMTcuNzQgMTMuNzYgMTggMTMuNCAxOC4xQzEyLjI4IDE4LjUgMTEuMTYgMTcuOTQgMTAuNSAxNy4yOEMxMS42OSAxNyAxMi40IDE2LjEyIDEyLjYxIDE1LjIzQzEyLjc4IDE0LjQzIDEyLjQ2IDEzLjc3IDEyLjMzIDEzQzEyLjIxIDEyLjI2IDEyLjIzIDExLjYzIDEyLjUgMTAuOTRDMTIuNjkgMTEuMzIgMTIuODkgMTEuNyAxMy4xMyAxMkMxMy45IDEzIDE1LjExIDEzLjQ0IDE1LjM3IDE0LjhDMTUuNDEgMTQuOTQgMTUuNDMgMTUuMDggMTUuNDMgMTUuMjNDMTUuNDYgMTYuMDUgMTUuMSAxNi45NSAxNC41IDE3LjVIMTQuNVoiIC8+PC9zdmc+", + "name": "ParticleEmitter3D", + "previewIconUrl": "https://asset-resources.gdevelop.io/public-resources/Icons/f2e5a34bf465f781866677762d385d6c8e9e8d203383f2df9a3b7e0fad6a2cb5_fire.svg", + "shortDescription": "Display a large number of particles in 3D to create visual effects in a 3D game.", + "version": "3.0.1", + "description": [ + "3D particle emitters let you create and display many small particles to simulate visual effects in your game — like fire, explosions, smoke, or dust.", + "", + "The parameters of the object can be configured in multiple different ways to create a specific desired effect. GDevelop will give a set of a pre-configured 3D particle emitters that you should try first.", + "", + "Use these 3D particle emitters in 3D games. For 2D games or particles that appear on a game's 2D user interface, use the 2D particle emitter object instead." + ], + "origin": { + "identifier": "ParticleEmitter3D", + "name": "gdevelop-extension-store" + }, + "tags": [ + "3d", + "particle", + "explosion", + "fire", + "smoke", + "splash", + "light" + ], + "authorIds": [ + "IWykYNRvhCZBN3vEgKEbBPOR3Oc2" + ], + "changelog": [ + { + "version": "3.0.0", + "breaking": "- the object rotates the other way around X axis." + }, + { + "version": "2.0.0", + "breaking": "- Object properties for position and rotation have been removed. They must be set with the instance editor or the action." + }, + { + "version": "1.0.0", + "breaking": "- Particles were 3 times too small." + } + ], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [], + "eventsFunctions": [ + { + "description": "Define helper classes JavaScript code.", + "fullName": "Define helper classes", + "functionType": "Action", + "name": "DefineHelperClasses", + "private": true, + "sentence": "Define helper classes JavaScript code", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "if (gdjs.__particleEmmiter3DExtension) {", + " return;", + "}", + "", + "const game = runtimeScene.getGame();", + "", + "class ParticleEmitter3DRenderer extends gdjs.CustomRuntimeObject3DRenderer {", + " constructor(", + " object,", + " instanceContainer,", + " parent", + " ) {", + " super(object, instanceContainer, parent);", + " }", + "", + " _updateThreeGroup() {", + " const threeObject3D = this.get3DRendererObject();", + "", + " threeObject3D.rotation.set(", + " gdjs.toRad(this._object.getRotationX()),", + " gdjs.toRad(this._object.getRotationY()),", + " gdjs.toRad(this._object.angle)", + " );", + "", + " threeObject3D.position.set(", + " this._object.getX(),", + " this._object.getY(),", + " this._object.getZ()", + " );", + "", + " // Force the scale to 1 because the particle emitter doesn't really has a size.", + " threeObject3D.scale.set(", + " this._object.isFlippedX() ? -1 : 1,", + " this._object.isFlippedY() ? -1 : 1,", + " this._object.isFlippedZ() ? -1 : 1", + " );", + "", + " threeObject3D.visible = !this._object.hidden;", + "", + " this._isContainerDirty = true;", + " }", + "}", + "", + "const coneLength = 64;", + "", + "class ParticleEmitterHelper extends THREE.Object3D {", + " /** @type {gdjs.CustomRuntimeObject3D} */", + " object;", + " /** @type {THREE.LineSegments} */", + " cone;", + " /** @type {THREE.LineSegments} */", + " centerLine;", + " /** @type {THREE.Mesh} */", + " originBox;", + "", + "\t/**", + " * @param gdjs.CustomRuntimeObject3D object", + "\t */", + " constructor(object) {", + " super();", + " this.object = object;", + " this.type = 'ParticleEmitterHelper';", + "", + " const coneGeometry = new THREE.BufferGeometry();", + " const conePositions = [", + " 0, 0, 0, 0, 0, 1,", + " 0, 0, 0, 1, 0, 1,", + " 0, 0, 0, - 1, 0, 1,", + " 0, 0, 0, 0, 1, 1,", + " 0, 0, 0, 0, - 1, 1", + " ];", + " for (let i = 0, j = 1, l = 32; i < l; i++ , j++) {", + " const p1 = (i / l) * Math.PI * 2;", + " const p2 = (j / l) * Math.PI * 2;", + " conePositions.push(", + " Math.cos(p1), Math.sin(p1), 1,", + " Math.cos(p2), Math.sin(p2), 1", + " );", + " }", + " coneGeometry.setAttribute('position', new THREE.Float32BufferAttribute(conePositions, 3));", + " this.cone = new THREE.LineSegments(", + " coneGeometry,", + " new THREE.LineBasicMaterial({ fog: false, toneMapped: false })", + " );", + " this.add(this.cone);", + " const centerLineGeometry = new THREE.BufferGeometry();", + " centerLineGeometry.setAttribute('position', new THREE.Float32BufferAttribute([", + " 0, 0, 0, 0, 0, coneLength", + " ], 3));", + " this.centerLine = new THREE.LineSegments(", + " centerLineGeometry,", + " new THREE.LineBasicMaterial({ fog: false, toneMapped: false })", + " );", + " this.add(this.centerLine);", + "", + " this.originBox = new THREE.Mesh(", + " new THREE.BoxGeometry(16, 16, 16),", + " new THREE.MeshBasicMaterial({ fog: false, toneMapped: false })", + " );", + " this.add(this.originBox);", + " this.update();", + "", + " this.originBox.gdjsRuntimeObject = object;", + " }", + "", + " dispose() {", + " this.cone.geometry.dispose();", + " this.cone.material.dispose();", + " this.centerLine.geometry.dispose();", + " this.centerLine.material.dispose();", + " this.originBox.geometry.dispose();", + " this.originBox.material.dispose();", + " }", + "", + " update() {", + " const coneWidth = coneLength * Math.sin(gdjs.toRad(this.object._getSpayConeAngle()));", + " const coneHeight = coneLength * Math.cos(gdjs.toRad(this.object._getSpayConeAngle()));", + " this.cone.scale.set(coneWidth, coneWidth, coneHeight);", + " const startColor = gdjs.rgbOrHexStringToNumber(this.object._getStartColor())", + " const endColor = gdjs.rgbOrHexStringToNumber(this.object._getEndColor());", + " this.cone.material.color.set(endColor);", + " this.centerLine.material.color.set(startColor);", + " this.originBox.material.color.set(startColor);", + " }", + "}", + "", + "/**", + " * @param {string} colorString", + " * @param {THREE.Vector4} threeColor", + " */", + "const setThreeColor = (colorString, threeColor = new THREE.Vector4()) => {", + " const integerColor = gdjs.rgbOrHexToRGBColor(colorString);", + " threeColor.x = integerColor[0] / 255;", + " threeColor.y = integerColor[1] / 255;", + " threeColor.z = integerColor[2] / 255;", + "};", + "", + "/**", + " * @param {string} integerOpacity", + " * @param {THREE.Vector4} threeColor", + " */", + "const setThreeOpacity = (integerOpacity, threeColor = new THREE.Vector4()) => {", + " threeColor.w = integerOpacity / 255;", + "};", + "", + "class ParticleEmitterAdapter {", + " /**", + " * @param particleSystem {ParticleSystem}", + " * @param colorOverLife {ColorOverLife}", + " * @param sizeOverLife {SizeOverLife}", + " * @param applyForce {ApplyForce}", + " */", + " constructor(particleSystem, colorOverLife, sizeOverLife, applyForce) {", + " this.particleSystem = particleSystem;", + " this.colorOverLife = colorOverLife;", + " this.sizeOverLife = sizeOverLife;", + " this.applyForce = applyForce;", + " }", + "", + " /**", + " * @param startColor {string}", + " */", + " setStartColor(startColor) {", + " setThreeColor(startColor, this.colorOverLife.color.color.keys[0][0]);", + " }", + "", + " /**", + " * @param endColor {string}", + " */", + " setEndColor(endColor) {", + " setThreeColor(endColor, this.colorOverLife.color.color.keys[1][0]);", + " }", + "", + " /**", + " * @param startOpacity {number}", + " */", + " setStartOpacity(startOpacity) {", + " this.colorOverLife.color.alpha.keys[0][0] = startOpacity / 255;", + " }", + "", + " /**", + " * @param endOpacity {number}", + " */", + " setEndOpacity(endOpacity) {", + " this.colorOverLife.color.alpha.keys[1][0] = endOpacity / 255;", + " }", + "", + " /**", + " * @param flow {number}", + " */", + " setFlow(flow) {", + " this.particleSystem.emissionOverTime.value = flow;", + " }", + "", + " /**", + " * @param startMinSize {number}", + " */", + " setStartMinSize(startMinSize) {", + " this.particleSystem.startSize.a = startMinSize;", + " }", + "", + " /**", + " * @param startMaxSize {number}", + " */", + " setStartMaxSize(startMaxSize) {", + " this.particleSystem.startSize.b = startMaxSize;", + " }", + "", + " /**", + " * @param endScale {number}", + " */", + " setEndScale(endScale) {", + " /** @type Bezier */", + " const bezier = this.sizeOverLife.size.functions[0][0];", + " bezier.p[0] = 1;", + " bezier.p[1] = gdjs.evtTools.common.lerp(1, endScale, 1 / 3);", + " bezier.p[2] = gdjs.evtTools.common.lerp(1, endScale, 2 / 3);", + " bezier.p[3] = endScale;", + " }", + "", + " /**", + " * @param startSpeedMin {number}", + " */", + " setStartSpeedMin(startSpeedMin) {", + " this.particleSystem.startSpeed.a = startSpeedMin;", + " }", + "", + " /**", + " * @param startSpeedMax {number}", + " */", + " setStartSpeedMax(startSpeedMax) {", + " this.particleSystem.startSpeed.b = startSpeedMax;", + " }", + "", + " /**", + " * @param lifespanMin {number}", + " */", + " setLifespanMin(lifespanMin) {", + " this.particleSystem.startLife.a = lifespanMin;", + " }", + "", + " /**", + " * @param lifespanMax {number}", + " */", + " setLifespanMax(lifespanMax) {", + " this.particleSystem.startLife.b = lifespanMax;", + " }", + "", + " /**", + " * @param duration {number}", + " */", + " setDuration(duration) {", + " this.particleSystem.duration = duration || Number.POSITIVE_INFINITY;", + " }", + "", + " /**", + " * @param areParticlesRelative {boolean}", + " */", + " setParticlesRelative(areParticlesRelative) {", + " this.particleSystem.worldSpace = !areParticlesRelative;", + " }", + "", + " /**", + " * @param sprayConeAngle {number}", + " */", + " setSprayConeAngle(sprayConeAngle) {", + " if (0 < sprayConeAngle && sprayConeAngle <= 180) {", + " if (!this.particleSystem.emitterShape.angle) {", + " this.particleSystem.emitterShape = new ConeEmitter({ radius: 0.1, angle: Math.PI / 8 });", + " }", + " this.particleSystem.emitterShape.angle = sprayConeAngle * Math.PI / 180;", + " }", + " else {", + " if (this.particleSystem.emitterShape.angle) {", + " this.particleSystem.emitterShape = new PointEmitter();", + " }", + " }", + " }", + "", + " /**", + " * @param blending {string}", + " */", + " setBlending(blendingString) {", + " const blending =", + " blendingString === \"Additive\" ? THREE.AdditiveBlending :", + " blendingString === \"Normal\" ? THREE.NormalBlending :", + " blendingString === \"Subtractive\" ? THREE.SubtractiveBlending :", + " blendingString === \"Multiply\" ? THREE.MultiplyBlending :", + " blendingString === \"None\" ? THREE.NoBlending :", + " THREE.AdditiveBlending;", + " // TODO This doesn't work.", + " this.particleSystem.blending = blending;", + " }", + "", + " /**", + " * @param gravity {number}", + " */", + " setGravity(gravity) {", + " this.applyForce.magnitude.value = gravity;", + " }", + "", + " /**", + " * @param gravityTop {string}", + " */", + " setGravityTop(gravityTop) {", + " // TODO Make gravity absolute even when \"relative\" is enabled. ", + " switch (gravityTop) {", + " case \"Z+\":", + " this.applyForce.direction.set(0, 0, -1);", + " break;", + "", + " case \"Y-\":", + " this.applyForce.direction.set(0, 1, 0);", + " break;", + " }", + " }", + "", + " setImage(resourceName) {", + " const texture = game.getImageManager().getThreeTexture(resourceName);", + " this.particleSystem.texture = texture;", + " }", + "}", + "", + "", + "", + "/**", + " * three.quarks v0.11.2 build Mon Jan 22 2024", + " * https://github.com/Alchemist0823/three.quarks#readme", + " * Copyright 2024 Alchemist0823 , MIT", + " */", + "", + "// The migration to addUpdateRange was backported without updating the library", + "// because GDevelop still uses Three.js 0.160.0.", + "", + "class ParticleEmitter extends THREE.Object3D {", + " constructor(system) {", + " super();", + " this.type = 'ParticleEmitter';", + " this.system = system;", + " }", + " clone() {", + " const system = this.system.clone();", + " system.emitter.copy(this, true);", + " return system.emitter;", + " }", + " dispose() { }", + " extractFromCache(cache) {", + " const values = [];", + " for (const key in cache) {", + " const data = cache[key];", + " delete data.metadata;", + " values.push(data);", + " }", + " return values;", + " }", + " toJSON(meta, options = {}) {", + " const isRootObject = meta === undefined || typeof meta === 'string';", + " const output = {};", + " if (isRootObject) {", + " meta = {", + " geometries: {},", + " materials: {},", + " textures: {},", + " images: {},", + " shapes: {},", + " skeletons: {},", + " animations: {},", + " nodes: {},", + " };", + " output.metadata = {", + " version: 4.5,", + " type: 'Object',", + " generator: 'Object3D.toJSON',", + " };", + " }", + " const object = {};", + " object.uuid = this.uuid;", + " object.type = this.type;", + " if (this.name !== '')", + " object.name = this.name;", + " if (this.castShadow === true)", + " object.castShadow = true;", + " if (this.receiveShadow === true)", + " object.receiveShadow = true;", + " if (this.visible === false)", + " object.visible = false;", + " if (this.frustumCulled === false)", + " object.frustumCulled = false;", + " if (this.renderOrder !== 0)", + " object.renderOrder = this.renderOrder;", + " if (JSON.stringify(this.userData) !== '{}')", + " object.userData = this.userData;", + " object.layers = this.layers.mask;", + " object.matrix = this.matrix.toArray();", + " if (this.matrixAutoUpdate === false)", + " object.matrixAutoUpdate = false;", + " if (this.system !== null)", + " object.ps = this.system.toJSON(meta, options);", + " if (this.children.length > 0) {", + " object.children = [];", + " for (let i = 0; i < this.children.length; i++) {", + " if (this.children[i].type !== 'ParticleSystemPreview') {", + " object.children.push(this.children[i].toJSON(meta).object);", + " }", + " }", + " }", + " if (isRootObject) {", + " const geometries = this.extractFromCache(meta.geometries);", + " const materials = this.extractFromCache(meta.materials);", + " const textures = this.extractFromCache(meta.textures);", + " const images = this.extractFromCache(meta.images);", + " if (geometries.length > 0)", + " output.geometries = geometries;", + " if (materials.length > 0)", + " output.materials = materials;", + " if (textures.length > 0)", + " output.textures = textures;", + " if (images.length > 0)", + " output.images = images;", + " }", + " output.object = object;", + " return output;", + " }", + "}", + "", + "class LinkedListNode {", + " constructor(data) {", + " this.data = data;", + " this.next = null;", + " this.prev = null;", + " }", + " hasPrev() {", + " return this.prev !== null;", + " }", + " hasNext() {", + " return this.next !== null;", + " }", + "}", + "class LinkedList {", + " constructor() {", + " this.length = 0;", + " this.head = this.tail = null;", + " }", + " isEmpty() {", + " return this.head === null;", + " }", + " clear() {", + " this.length = 0;", + " this.head = this.tail = null;", + " }", + " front() {", + " if (this.head === null)", + " return null;", + " return this.head.data;", + " }", + " back() {", + " if (this.tail === null)", + " return null;", + " return this.tail.data;", + " }", + " dequeue() {", + " if (this.head) {", + " const value = this.head.data;", + " this.head = this.head.next;", + " if (!this.head) {", + " this.tail = null;", + " }", + " else {", + " this.head.prev = null;", + " }", + " this.length--;", + " return value;", + " }", + " return undefined;", + " }", + " pop() {", + " if (this.tail) {", + " const value = this.tail.data;", + " this.tail = this.tail.prev;", + " if (!this.tail) {", + " this.head = null;", + " }", + " else {", + " this.tail.next = null;", + " }", + " this.length--;", + " return value;", + " }", + " return undefined;", + " }", + " queue(data) {", + " const node = new LinkedListNode(data);", + " if (!this.tail) {", + " this.tail = node;", + " }", + " if (this.head) {", + " this.head.prev = node;", + " node.next = this.head;", + " }", + " this.head = node;", + " this.length++;", + " }", + " push(data) {", + " const node = new LinkedListNode(data);", + " if (!this.head) {", + " this.head = node;", + " }", + " if (this.tail) {", + " this.tail.next = node;", + " node.prev = this.tail;", + " }", + " this.tail = node;", + " this.length++;", + " }", + " insertBefore(node, data) {", + " const newNode = new LinkedListNode(data);", + " newNode.next = node;", + " newNode.prev = node.prev;", + " if (newNode.prev !== null) {", + " newNode.prev.next = newNode;", + " }", + " newNode.next.prev = newNode;", + " if (node == this.head) {", + " this.head = newNode;", + " }", + " this.length++;", + " }", + " remove(data) {", + " if (this.head === null || this.tail === null) {", + " return;", + " }", + " let tempNode = this.head;", + " if (data === this.head.data) {", + " this.head = this.head.next;", + " }", + " if (data === this.tail.data) {", + " this.tail = this.tail.prev;", + " }", + " while (tempNode.next !== null && tempNode.data !== data) {", + " tempNode = tempNode.next;", + " }", + " if (tempNode.data === data) {", + " if (tempNode.prev !== null)", + " tempNode.prev.next = tempNode.next;", + " if (tempNode.next !== null)", + " tempNode.next.prev = tempNode.prev;", + " this.length--;", + " }", + " }", + " *values() {", + " let current = this.head;", + " while (current !== null) {", + " yield current.data;", + " current = current.next;", + " }", + " }", + "}", + "", + "class NodeParticle {", + " constructor() {", + " this.position = new THREE.Vector3();", + " this.velocity = new THREE.Vector3();", + " this.age = 0;", + " this.life = 1;", + " this.size = 1;", + " this.rotation = 0;", + " this.color = new THREE.Vector4(1, 1, 1, 1);", + " this.uvTile = 0;", + " }", + " get died() {", + " return this.age >= this.life;", + " }", + " reset() {", + " this.position.set(0, 0, 0);", + " this.velocity.set(0, 0, 0);", + " this.age = 0;", + " this.life = 1;", + " this.size = 1;", + " this.rotation = 0;", + " this.color.set(1, 1, 1, 1);", + " this.uvTile = 0;", + " }", + "}", + "class SpriteParticle {", + " constructor() {", + " this.startSpeed = 0;", + " this.startColor = new THREE.Vector4();", + " this.startSize = 1;", + " this.position = new THREE.Vector3();", + " this.velocity = new THREE.Vector3();", + " this.age = 0;", + " this.life = 1;", + " this.size = 1;", + " this.speedModifier = 1;", + " this.rotation = 0;", + " this.color = new THREE.Vector4();", + " this.uvTile = 0;", + " }", + " get died() {", + " return this.age >= this.life;", + " }", + "}", + "class RecordState {", + " constructor(position, size, color) {", + " this.position = position;", + " this.size = size;", + " this.color = color;", + " }", + "}", + "class TrailParticle {", + " constructor() {", + " this.startSpeed = 0;", + " this.startColor = new THREE.Vector4();", + " this.startSize = 1;", + " this.position = new THREE.Vector3();", + " this.velocity = new THREE.Vector3();", + " this.age = 0;", + " this.life = 1;", + " this.size = 1;", + " this.length = 100;", + " this.speedModifier = 1;", + " this.color = new THREE.Vector4();", + " this.previous = new LinkedList();", + " this.uvTile = 0;", + " }", + " update() {", + " if (this.age <= this.life) {", + " this.previous.push(new RecordState(this.position.clone(), this.size, this.color.clone()));", + " }", + " else {", + " if (this.previous.length > 0) {", + " this.previous.dequeue();", + " }", + " }", + " while (this.previous.length > this.length) {", + " this.previous.dequeue();", + " }", + " }", + " get died() {", + " return this.age >= this.life;", + " }", + " reset() {", + " this.previous.clear();", + " }", + "}", + "", + "class Bezier {", + " constructor(p1, p2, p3, p4) {", + " this.p = [p1, p2, p3, p4];", + " }", + " genValue(t) {", + " const t2 = t * t;", + " const t3 = t * t * t;", + " const mt = 1 - t;", + " const mt2 = mt * mt;", + " const mt3 = mt2 * mt;", + " return this.p[0] * mt3 + this.p[1] * mt2 * t * 3 + this.p[2] * mt * t2 * 3 + this.p[3] * t3;", + " }", + " derivativeCoefficients(points) {", + " const dpoints = [];", + " for (let p = points, c = p.length - 1; c > 0; c--) {", + " const list = [];", + " for (let j = 0; j < c; j++) {", + " const dpt = c * (p[j + 1] - p[j]);", + " list.push(dpt);", + " }", + " dpoints.push(list);", + " p = list;", + " }", + " return dpoints;", + " }", + " getSlope(t) {", + " const p = this.derivativeCoefficients(this.p)[0];", + " const mt = 1 - t;", + " const a = mt * mt;", + " const b = mt * t * 2;", + " const c = t * t;", + " return a * p[0] + b * p[1] + c * p[2];", + " }", + " controlCurve(d0, d1) {", + " this.p[1] = d0 / 3 + this.p[0];", + " this.p[2] = this.p[3] - d1 / 3;", + " }", + " hull(t) {", + " let p = this.p;", + " let _p = [], pt, idx = 0, i = 0, l = 0;", + " const q = [];", + " q[idx++] = p[0];", + " q[idx++] = p[1];", + " q[idx++] = p[2];", + " q[idx++] = p[3];", + " while (p.length > 1) {", + " _p = [];", + " for (i = 0, l = p.length - 1; i < l; i++) {", + " pt = t * p[i] + (1 - t) * p[i + 1];", + " q[idx++] = pt;", + " _p.push(pt);", + " }", + " p = _p;", + " }", + " return q;", + " }", + " split(t) {", + " const q = this.hull(t);", + " const result = {", + " left: new Bezier(q[0], q[4], q[7], q[9]),", + " right: new Bezier(q[9], q[8], q[6], q[3]),", + " span: q", + " };", + " return result;", + " }", + " clone() {", + " return new Bezier(this.p[0], this.p[1], this.p[2], this.p[3]);", + " }", + " toJSON() {", + " return {", + " p0: this.p[0],", + " p1: this.p[1],", + " p2: this.p[2],", + " p3: this.p[3],", + " };", + " }", + " static fromJSON(json) {", + " return new Bezier(json.p0, json.p1, json.p2, json.p3);", + " }", + "}", + "", + "const ColorToJSON = (color) => {", + " return { r: color.x, g: color.y, b: color.z, a: color.w };", + "};", + "const JSONToColor = (json) => {", + " return new THREE.Vector4(json.r, json.g, json.b, json.a);", + "};", + "const JSONToValue = (json, type) => {", + " switch (type) {", + " case 'Vector3':", + " return new THREE.Vector3(json.x, json.y, json.z);", + " case 'Vector4':", + " return new THREE.Vector4(json.x, json.y, json.z, json.w);", + " case 'Color':", + " return new THREE.Vector3(json.r, json.g, json.b);", + " case 'Number':", + " return json;", + " default:", + " return json;", + " }", + "};", + "const ValueToJSON = (value, type) => {", + " switch (type) {", + " case 'Vector3':", + " return { x: value.x, y: value.y, z: value.z };", + " case 'Vector4':", + " return { x: value.x, y: value.y, z: value.z, w: value.w };", + " case 'Color':", + " return { r: value.x, g: value.y, b: value.z };", + " case 'Number':", + " return value;", + " default:", + " return value;", + " }", + "};", + "", + "class RandomColor {", + " constructor(a, b) {", + " this.a = a;", + " this.b = b;", + " this.type = \"value\";", + " }", + " genColor(color) {", + " const rand = Math.random();", + " return color.copy(this.a).lerp(this.b, rand);", + " }", + " toJSON() {", + " return {", + " type: \"RandomColor\",", + " a: ColorToJSON(this.a),", + " b: ColorToJSON(this.b),", + " };", + " }", + " static fromJSON(json) {", + " return new RandomColor(JSONToColor(json.a), JSONToColor(json.b));", + " }", + " clone() {", + " return new RandomColor(this.a.clone(), this.b.clone());", + " }", + "}", + "", + "class ColorRange {", + " constructor(a, b) {", + " this.a = a;", + " this.b = b;", + " this.type = 'value';", + " }", + " genColor(color, t) {", + " return color.copy(this.a).lerp(this.b, Math.random());", + " }", + " toJSON() {", + " return {", + " type: 'ColorRange',", + " a: ColorToJSON(this.a),", + " b: ColorToJSON(this.b),", + " };", + " }", + " static fromJSON(json) {", + " return new ColorRange(JSONToColor(json.a), JSONToColor(json.b));", + " }", + " clone() {", + " return new ColorRange(this.a.clone(), this.b.clone());", + " }", + "}", + "", + "class ContinuousLinearFunction {", + " constructor(keys, subType) {", + " this.subType = subType;", + " this.type = 'function';", + " this.keys = keys;", + " }", + " findKey(t) {", + " let mid = 0;", + " let left = 0, right = this.keys.length - 1;", + " while (left + 1 < right) {", + " mid = Math.floor((left + right) / 2);", + " if (t < this.getStartX(mid))", + " right = mid - 1;", + " else if (t > this.getEndX(mid))", + " left = mid + 1;", + " else", + " return mid;", + " }", + " for (let i = left; i <= right; i++) {", + " if (t >= this.getStartX(i) && t <= this.getEndX(i))", + " return i;", + " }", + " return -1;", + " }", + " getStartX(index) {", + " return this.keys[index][1];", + " }", + " getEndX(index) {", + " if (index + 1 < this.keys.length)", + " return this.keys[index + 1][1];", + " return 1;", + " }", + " genValue(value, t) {", + " const index = this.findKey(t);", + " if (this.subType === 'Number') {", + " if (index === -1) {", + " return this.keys[0][0];", + " }", + " else if (index + 1 >= this.keys.length) {", + " return this.keys[this.keys.length - 1][0];", + " }", + " return ((this.keys[index + 1][0] - this.keys[index][0]) *", + " ((t - this.getStartX(index)) / (this.getEndX(index) - this.getStartX(index))) +", + " this.keys[index][0]);", + " }", + " else {", + " if (index === -1) {", + " return value.copy(this.keys[0][0]);", + " }", + " if (index + 1 >= this.keys.length) {", + " return value.copy(this.keys[this.keys.length - 1][0]);", + " }", + " return value", + " .copy(this.keys[index][0])", + " .lerp(this.keys[index + 1][0], (t - this.getStartX(index)) / (this.getEndX(index) - this.getStartX(index)));", + " }", + " }", + " toJSON() {", + " this.keys[0][0].constructor.name;", + " return {", + " type: 'CLinearFunction',", + " subType: this.subType,", + " keys: this.keys.map(([color, pos]) => ({ value: ValueToJSON(color, this.subType), pos: pos })),", + " };", + " }", + " static fromJSON(json) {", + " return new ContinuousLinearFunction(json.keys.map((pair) => [JSONToValue(pair.value, json.subType), pair.pos]), json.subType);", + " }", + " clone() {", + " if (this.subType === 'Number') {", + " return new ContinuousLinearFunction(this.keys.map(([value, pos]) => [value, pos]), this.subType);", + " }", + " else {", + " return new ContinuousLinearFunction(this.keys.map(([value, pos]) => [value.clone(), pos]), this.subType);", + " }", + " }", + "}", + "", + "const tempVec3 = new THREE.Vector3();", + "class Gradient {", + " constructor(color = [", + " [new THREE.Vector3(0, 0, 0), 0],", + " [new THREE.Vector3(1, 1, 1), 0],", + " ], alpha = [", + " [1, 0],", + " [1, 1],", + " ]) {", + " this.type = 'function';", + " this.color = new ContinuousLinearFunction(color, 'Color');", + " this.alpha = new ContinuousLinearFunction(alpha, 'Number');", + " }", + " genColor(color, t) {", + " this.color.genValue(tempVec3, t);", + " return color.set(tempVec3.x, tempVec3.y, tempVec3.z, this.alpha.genValue(1, t));", + " }", + " toJSON() {", + " return {", + " type: 'Gradient',", + " color: this.color.toJSON(),", + " alpha: this.alpha.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " if (json.functions) {", + " const keys = json.functions.map((func) => [ColorRange.fromJSON(func.function).a, func.start]);", + " if (json.functions.length > 0) {", + " keys.push([ColorRange.fromJSON(json.functions[json.functions.length - 1].function).b, 1]);", + " }", + " return new Gradient(keys.map((key) => [new THREE.Vector3(key[0].x, key[0].y, key[0].z), key[1]]), keys.map((key) => [key[0].w, key[1]]));", + " }", + " else {", + " const gradient = new Gradient();", + " gradient.alpha = ContinuousLinearFunction.fromJSON(json.alpha);", + " gradient.color = ContinuousLinearFunction.fromJSON(json.color);", + " return gradient;", + " }", + " }", + " clone() {", + " const gradient = new Gradient();", + " gradient.alpha = this.alpha.clone();", + " gradient.color = this.color.clone();", + " return gradient;", + " }", + "}", + "", + "const tempColor = new THREE.Vector4();", + "class RandomColorBetweenGradient {", + " constructor(gradient1, gradient2) {", + " this.type = 'memorizedFunction';", + " this.gradient1 = gradient1;", + " this.gradient2 = gradient2;", + " }", + " startGen(memory) {", + " memory.rand = Math.random();", + " }", + " genColor(color, t, memory) {", + " this.gradient1.genColor(color, t);", + " this.gradient2.genColor(tempColor, t);", + " if (memory && memory.rand) {", + " color.lerp(tempColor, memory.rand);", + " }", + " else {", + " color.lerp(tempColor, Math.random());", + " }", + " return color;", + " }", + " toJSON() {", + " return {", + " type: 'RandomColorBetweenGradient',", + " gradient1: this.gradient1.toJSON(),", + " gradient2: this.gradient2.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new RandomColorBetweenGradient(Gradient.fromJSON(json.gradient1), Gradient.fromJSON(json.gradient2));", + " }", + " clone() {", + " return new RandomColorBetweenGradient(this.gradient1.clone(), this.gradient2.clone());", + " }", + "}", + "", + "class ConstantColor {", + " constructor(color) {", + " this.color = color;", + " this.type = 'value';", + " }", + " genColor(color) {", + " return color.copy(this.color);", + " }", + " toJSON() {", + " return {", + " type: 'ConstantColor',", + " color: ColorToJSON(this.color),", + " };", + " }", + " static fromJSON(json) {", + " return new ConstantColor(JSONToColor(json.color));", + " }", + " clone() {", + " return new ConstantColor(this.color.clone());", + " }", + "}", + "function ColorGeneratorFromJSON(json) {", + " switch (json.type) {", + " case 'ConstantColor':", + " return ConstantColor.fromJSON(json);", + " case 'ColorRange':", + " return ColorRange.fromJSON(json);", + " case 'RandomColor':", + " return RandomColor.fromJSON(json);", + " case 'Gradient':", + " return Gradient.fromJSON(json);", + " case 'RandomColorBetweenGradient':", + " return RandomColorBetweenGradient.fromJSON(json);", + " default:", + " return new ConstantColor(new THREE.Vector4(1, 1, 1, 1));", + " }", + "}", + "", + "class ConstantValue {", + " constructor(value) {", + " this.value = value;", + " this.type = 'value';", + " }", + " genValue() {", + " return this.value;", + " }", + " toJSON() {", + " return {", + " type: \"ConstantValue\",", + " value: this.value", + " };", + " }", + " static fromJSON(json) {", + " return new ConstantValue(json.value);", + " }", + " clone() {", + " return new ConstantValue(this.value);", + " }", + "}", + "", + "class IntervalValue {", + " constructor(a, b) {", + " this.a = a;", + " this.b = b;", + " this.type = 'value';", + " }", + " genValue() {", + " return THREE.MathUtils.lerp(this.a, this.b, Math.random());", + " }", + " toJSON() {", + " return {", + " type: 'IntervalValue',", + " a: this.a,", + " b: this.b,", + " };", + " }", + " static fromJSON(json) {", + " return new IntervalValue(json.a, json.b);", + " }", + " clone() {", + " return new IntervalValue(this.a, this.b);", + " }", + "}", + "", + "class PiecewiseFunction {", + " constructor() {", + " this.functions = new Array();", + " }", + " findFunction(t) {", + " let mid = 0;", + " let left = 0, right = this.functions.length - 1;", + " while (left + 1 < right) {", + " mid = Math.floor((left + right) / 2);", + " if (t < this.getStartX(mid))", + " right = mid - 1;", + " else if (t > this.getEndX(mid))", + " left = mid + 1;", + " else", + " return mid;", + " }", + " for (let i = left; i <= right; i++) {", + " if (t >= this.functions[i][1] && t <= this.getEndX(i))", + " return i;", + " }", + " return -1;", + " }", + " getStartX(index) {", + " return this.functions[index][1];", + " }", + " setStartX(index, x) {", + " if (index > 0)", + " this.functions[index][1] = x;", + " }", + " getEndX(index) {", + " if (index + 1 < this.functions.length)", + " return this.functions[index + 1][1];", + " return 1;", + " }", + " setEndX(index, x) {", + " if (index + 1 < this.functions.length)", + " this.functions[index + 1][1] = x;", + " }", + " insertFunction(t, func) {", + " const index = this.findFunction(t);", + " this.functions.splice(index + 1, 0, [func, t]);", + " }", + " removeFunction(index) {", + " return this.functions.splice(index, 1)[0][0];", + " }", + " getFunction(index) {", + " return this.functions[index][0];", + " }", + " setFunction(index, func) {", + " this.functions[index][0] = func;", + " }", + " get numOfFunctions() {", + " return this.functions.length;", + " }", + "}", + "", + "class PiecewiseBezier extends PiecewiseFunction {", + " constructor(curves = [[new Bezier(0, 1.0 / 3, 1.0 / 3 * 2, 1), 0]]) {", + " super();", + " this.type = \"function\";", + " this.functions = curves;", + " }", + " genValue(t = 0) {", + " const index = this.findFunction(t);", + " if (index === -1) {", + " return 0;", + " }", + " return this.functions[index][0].genValue((t - this.getStartX(index)) / (this.getEndX(index) - this.getStartX(index)));", + " }", + " toSVG(length, segments) {", + " if (segments < 1)", + " return \"\";", + " let result = [\"M\", 0, this.functions[0][0].p[0]].join(\" \");", + " for (let i = 1.0 / segments; i <= 1; i += 1.0 / segments) {", + " result = [result, \"L\", i * length, this.genValue(i)].join(\" \");", + " }", + " return result;", + " }", + " toJSON() {", + " return {", + " type: \"PiecewiseBezier\",", + " functions: this.functions.map(([bezier, start]) => ({ function: bezier.toJSON(), start: start })),", + " };", + " }", + " static fromJSON(json) {", + " return new PiecewiseBezier(json.functions.map((piecewiseFunction) => ([Bezier.fromJSON(piecewiseFunction.function), piecewiseFunction.start])));", + " }", + " clone() {", + " return new PiecewiseBezier(this.functions.map(([bezier, start]) => ([bezier.clone(), start])));", + " }", + "}", + "", + "function ValueGeneratorFromJSON(json) {", + " switch (json.type) {", + " case 'ConstantValue':", + " return ConstantValue.fromJSON(json);", + " case 'IntervalValue':", + " return IntervalValue.fromJSON(json);", + " case 'PiecewiseBezier':", + " return PiecewiseBezier.fromJSON(json);", + " default:", + " return new ConstantValue(0);", + " }", + "}", + "", + "class RandomQuatGenerator {", + " constructor() {", + " this.type = \"rotation\";", + " }", + " genValue(quat, t) {", + " let x, y, z, u, v, w;", + " do {", + " x = Math.random() * 2 - 1;", + " y = Math.random() * 2 - 1;", + " z = x * x + y * y;", + " } while (z > 1);", + " do {", + " u = Math.random() * 2 - 1;", + " v = Math.random() * 2 - 1;", + " w = u * u + v * v;", + " } while (w > 1);", + " const s = Math.sqrt((1 - z) / w);", + " quat.set(x, y, s * u, s * v);", + " return quat;", + " }", + " toJSON() {", + " return {", + " type: \"RandomQuat\"", + " };", + " }", + " static fromJSON(json) {", + " return new RandomQuatGenerator();", + " }", + " clone() {", + " return new RandomQuatGenerator();", + " }", + "}", + "", + "class AxisAngleGenerator {", + " constructor(axis, angle) {", + " this.axis = axis;", + " this.angle = angle;", + " this.type = 'rotation';", + " }", + " genValue(quat, t) {", + " return quat.setFromAxisAngle(this.axis, this.angle.genValue(t));", + " }", + " toJSON() {", + " return {", + " type: 'AxisAngle',", + " axis: { x: this.axis.x, y: this.axis.y, z: this.axis.z },", + " angle: this.angle.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new AxisAngleGenerator(new THREE.Vector3(json.axis.x, json.axis.y, json.axis.z), ValueGeneratorFromJSON(json.angle));", + " }", + " clone() {", + " return new AxisAngleGenerator(this.axis.clone(), this.angle.clone());", + " }", + "}", + "", + "class EulerGenerator {", + " constructor(angleX, angleY, angleZ, eulerOrder) {", + " this.angleX = angleX;", + " this.angleY = angleY;", + " this.angleZ = angleZ;", + " this.type = 'rotation';", + " this.eular = new THREE.Euler(0, 0, 0, eulerOrder);", + " }", + " genValue(quat, t) {", + " this.eular.set(this.angleX.genValue(t), this.angleY.genValue(t), this.angleZ.genValue(t));", + " return quat.setFromEuler(this.eular);", + " }", + " toJSON() {", + " return {", + " type: 'Euler',", + " angleX: this.angleX.toJSON(),", + " angleY: this.angleY.toJSON(),", + " angleZ: this.angleZ.toJSON(),", + " eulerOrder: this.eular.order,", + " };", + " }", + " static fromJSON(json) {", + " return new EulerGenerator(ValueGeneratorFromJSON(json.angleX), ValueGeneratorFromJSON(json.angleY), ValueGeneratorFromJSON(json.angleZ), json.eulerOrder);", + " }", + " clone() {", + " return new EulerGenerator(this.angleX, this.angleY, this.angleZ, this.eular.order);", + " }", + "}", + "", + "function RotationGeneratorFromJSON(json) {", + " switch (json.type) {", + " case 'AxisAngle':", + " return AxisAngleGenerator.fromJSON(json);", + " case 'Euler':", + " return EulerGenerator.fromJSON(json);", + " case 'RandomQuat':", + " return RandomQuatGenerator.fromJSON(json);", + " default:", + " return new RandomQuatGenerator();", + " }", + "}", + "", + "function GeneratorFromJSON(json) {", + " switch (json.type) {", + " case 'ConstantValue':", + " case 'IntervalValue':", + " case 'PiecewiseBezier':", + " return ValueGeneratorFromJSON(json);", + " case 'AxisAngle':", + " case 'RandomQuat':", + " case 'Euler':", + " return RotationGeneratorFromJSON(json);", + " default:", + " return new ConstantValue(0);", + " }", + "}", + "", + "class ColorOverLife {", + " constructor(color) {", + " this.color = color;", + " this.type = 'ColorOverLife';", + " }", + " initialize(particle) {", + " if (this.color.type === 'memorizedFunction') {", + " particle.colorOverLifeMemory = {};", + " this.color.startGen(particle.colorOverLifeMemory);", + " }", + " }", + " update(particle, delta) {", + " if (this.color.type === 'memorizedFunction') {", + " this.color.genColor(particle.color, particle.age / particle.life, particle.colorOverLifeMemory);", + " }", + " else {", + " this.color.genColor(particle.color, particle.age / particle.life);", + " }", + " particle.color.x *= particle.startColor.x;", + " particle.color.y *= particle.startColor.y;", + " particle.color.z *= particle.startColor.z;", + " particle.color.w *= particle.startColor.w;", + " }", + " frameUpdate(delta) { }", + " toJSON() {", + " return {", + " type: this.type,", + " color: this.color.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new ColorOverLife(ColorGeneratorFromJSON(json.color));", + " }", + " clone() {", + " return new ColorOverLife(this.color.clone());", + " }", + " reset() { }", + "}", + "", + "class RotationOverLife {", + " constructor(angularVelocity) {", + " this.angularVelocity = angularVelocity;", + " this.type = 'RotationOverLife';", + " this.dynamic = !(angularVelocity instanceof ConstantValue || angularVelocity instanceof IntervalValue);", + " }", + " initialize(particle) {", + " this.dynamic = !(this.angularVelocity instanceof ConstantValue || this.angularVelocity instanceof IntervalValue);", + " if (!this.dynamic && typeof particle.rotation === 'number') {", + " particle.angularVelocity = this.angularVelocity.genValue();", + " }", + " }", + " update(particle, delta) {", + " if (!this.dynamic) {", + " if (typeof particle.rotation === 'number') {", + " particle.rotation += delta * particle.angularVelocity;", + " }", + " }", + " else {", + " if (typeof particle.rotation === 'number') {", + " particle.rotation +=", + " delta * this.angularVelocity.genValue(particle.age / particle.life);", + " }", + " }", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " angularVelocity: this.angularVelocity.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new RotationOverLife(ValueGeneratorFromJSON(json.angularVelocity));", + " }", + " frameUpdate(delta) { }", + " clone() {", + " return new RotationOverLife(this.angularVelocity.clone());", + " }", + " reset() { }", + "}", + "", + "const IdentityQuaternion = new THREE.Quaternion();", + "class Rotation3DOverLife {", + " constructor(angularVelocity) {", + " this.angularVelocity = angularVelocity;", + " this.type = 'Rotation3DOverLife';", + " this.tempQuat = new THREE.Quaternion();", + " this.dynamic = !(angularVelocity instanceof RandomQuatGenerator);", + " }", + " initialize(particle) {", + " this.dynamic = !(this.angularVelocity instanceof RandomQuatGenerator);", + " if (particle.rotation instanceof THREE.Quaternion) {", + " particle.angularVelocity = new THREE.Quaternion();", + " this.angularVelocity.genValue(particle.angularVelocity);", + " }", + " }", + " update(particle, delta) {", + " if (particle.rotation instanceof THREE.Quaternion) {", + " if (!this.dynamic) {", + " this.tempQuat.slerpQuaternions(IdentityQuaternion, particle.angularVelocity, delta);", + " particle.rotation.multiply(this.tempQuat);", + " }", + " else {", + " this.angularVelocity.genValue(this.tempQuat, particle.age / particle.life);", + " this.tempQuat.slerpQuaternions(IdentityQuaternion, this.tempQuat, delta);", + " particle.rotation.multiply(this.tempQuat);", + " }", + " }", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " angularVelocity: this.angularVelocity.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new Rotation3DOverLife(RotationGeneratorFromJSON(json.angularVelocity));", + " }", + " frameUpdate(delta) { }", + " clone() {", + " return new Rotation3DOverLife(this.angularVelocity.clone());", + " }", + " reset() { }", + "}", + "", + "class ForceOverLife {", + " initialize(particle) { }", + " constructor(x, y, z) {", + " this.x = x;", + " this.y = y;", + " this.z = z;", + " this.type = 'ForceOverLife';", + " this._temp = new THREE.Vector3();", + " }", + " update(particle, delta) {", + " this._temp.set(this.x.genValue(particle.age / particle.life), this.y.genValue(particle.age / particle.life), this.z.genValue(particle.age / particle.life));", + " particle.velocity.addScaledVector(this._temp, delta);", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " x: this.x.toJSON(),", + " y: this.y.toJSON(),", + " z: this.z.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new ForceOverLife(ValueGeneratorFromJSON(json.x), ValueGeneratorFromJSON(json.y), ValueGeneratorFromJSON(json.z));", + " }", + " frameUpdate(delta) { }", + " clone() {", + " return new ForceOverLife(this.x.clone(), this.y.clone(), this.z.clone());", + " }", + " reset() { }", + "}", + "", + "class SizeOverLife {", + " initialize(particle) {", + " }", + " constructor(size) {", + " this.size = size;", + " this.type = 'SizeOverLife';", + " }", + " update(particle) {", + " particle.size = particle.startSize * this.size.genValue(particle.age / particle.life);", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " size: this.size.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new SizeOverLife(ValueGeneratorFromJSON(json.size));", + " }", + " frameUpdate(delta) {", + " }", + " clone() {", + " return new SizeOverLife(this.size.clone());", + " }", + " reset() {", + " }", + "}", + "", + "class SpeedOverLife {", + " initialize(particle) {", + " }", + " constructor(speed) {", + " this.speed = speed;", + " this.type = 'SpeedOverLife';", + " }", + " update(particle) {", + " particle.speedModifier = this.speed.genValue(particle.age / particle.life);", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " speed: this.speed.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new SpeedOverLife(ValueGeneratorFromJSON(json.speed));", + " }", + " frameUpdate(delta) {", + " }", + " clone() {", + " return new SpeedOverLife(this.speed.clone());", + " }", + " reset() {", + " }", + "}", + "", + "class FrameOverLife {", + " constructor(frame) {", + " this.frame = frame;", + " this.type = 'FrameOverLife';", + " }", + " initialize(particle) {", + " if (!(this.frame instanceof PiecewiseBezier)) {", + " particle.uvTile = Math.floor(this.frame.genValue(0) + 0.001);", + " }", + " }", + " update(particle, delta) {", + " if (this.frame instanceof PiecewiseBezier) {", + " particle.uvTile = Math.floor(this.frame.genValue(particle.age / particle.life) + 0.001);", + " }", + " }", + " frameUpdate(delta) { }", + " toJSON() {", + " return {", + " type: this.type,", + " frame: this.frame.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new FrameOverLife(ValueGeneratorFromJSON(json.frame));", + " }", + " clone() {", + " return new FrameOverLife(this.frame.clone());", + " }", + " reset() { }", + "}", + "", + "new THREE.Vector3(0, 0, 1);", + "class OrbitOverLife {", + " constructor(orbitSpeed, axis = new THREE.Vector3(0, 1, 0)) {", + " this.orbitSpeed = orbitSpeed;", + " this.axis = axis;", + " this.type = 'OrbitOverLife';", + " this.temp = new THREE.Vector3();", + " this.rotation = new THREE.Quaternion();", + " this.line = new THREE.Line3();", + " }", + " initialize(particle) {", + " }", + " update(particle, delta) {", + " this.line.set(new THREE.Vector3(0, 0, 0), this.axis);", + " this.line.closestPointToPoint(particle.position, false, this.temp);", + " this.rotation.setFromAxisAngle(this.axis, this.orbitSpeed.genValue(particle.age / particle.life) * delta);", + " particle.position.sub(this.temp);", + " particle.position.applyQuaternion(this.rotation);", + " particle.position.add(this.temp);", + " }", + " frameUpdate(delta) {", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " orbitSpeed: this.orbitSpeed.toJSON(),", + " axis: [this.axis.x, this.axis.y, this.axis.z],", + " };", + " }", + " static fromJSON(json) {", + " return new OrbitOverLife(ValueGeneratorFromJSON(json.orbitSpeed), json.axis ? new THREE.Vector3(json.axis[0], json.axis[1], json.axis[2]) : undefined);", + " }", + " clone() {", + " return new OrbitOverLife(this.orbitSpeed.clone());", + " }", + " reset() {", + " }", + "}", + "", + "class WidthOverLength {", + " initialize(particle) {", + " }", + " constructor(width) {", + " this.width = width;", + " this.type = 'WidthOverLength';", + " }", + " update(particle) {", + " if (particle instanceof TrailParticle) {", + " const iter = particle.previous.values();", + " for (let i = 0; i < particle.previous.length; i++) {", + " const cur = iter.next();", + " cur.value.size = this.width.genValue((particle.previous.length - i) / particle.length);", + " }", + " }", + " }", + " frameUpdate(delta) {", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " width: this.width.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new WidthOverLength(ValueGeneratorFromJSON(json.width));", + " }", + " clone() {", + " return new WidthOverLength(this.width.clone());", + " }", + " reset() {", + " }", + "}", + "", + "class ApplyForce {", + " constructor(direction, magnitude) {", + " this.direction = direction;", + " this.magnitude = magnitude;", + " this.type = 'ApplyForce';", + " this.magnitudeValue = this.magnitude.genValue();", + " }", + " initialize(particle) {", + " }", + " update(particle, delta) {", + " particle.velocity.addScaledVector(this.direction, this.magnitudeValue * delta);", + " }", + " frameUpdate(delta) {", + " this.magnitudeValue = this.magnitude.genValue();", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " direction: [this.direction.x, this.direction.y, this.direction.z],", + " magnitude: this.magnitude.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " var _a;", + " return new ApplyForce(new THREE.Vector3(json.direction[0], json.direction[1], json.direction[2]), ValueGeneratorFromJSON((_a = json.magnitude) !== null && _a !== void 0 ? _a : json.force));", + " }", + " clone() {", + " return new ApplyForce(this.direction.clone(), this.magnitude.clone());", + " }", + " reset() {", + " }", + "}", + "", + "class GravityForce {", + " constructor(center, magnitude) {", + " this.center = center;", + " this.magnitude = magnitude;", + " this.type = 'GravityForce';", + " this.temp = new THREE.Vector3();", + " }", + " initialize(particle) {", + " }", + " update(particle, delta) {", + " this.temp.copy(this.center).sub(particle.position).normalize();", + " particle.velocity.addScaledVector(this.temp, this.magnitude / particle.position.distanceToSquared(this.center) * delta);", + " }", + " frameUpdate(delta) {", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " center: [this.center.x, this.center.y, this.center.z],", + " magnitude: this.magnitude,", + " };", + " }", + " static fromJSON(json) {", + " return new GravityForce(new THREE.Vector3(json.center[0], json.center[1], json.center[2]), json.magnitude);", + " }", + " clone() {", + " return new GravityForce(this.center.clone(), this.magnitude);", + " }", + " reset() {", + " }", + "}", + "", + "new THREE.Vector3(0, 0, 1);", + "class ChangeEmitDirection {", + " constructor(angle) {", + " this.angle = angle;", + " this.type = 'ChangeEmitDirection';", + " this._temp = new THREE.Vector3();", + " this._q = new THREE.Quaternion();", + " }", + " initialize(particle) {", + " const len = particle.velocity.length();", + " if (len == 0)", + " return;", + " particle.velocity.normalize();", + " if (particle.velocity.x === 0 && particle.velocity.y === 0) {", + " this._temp.set(0, particle.velocity.z, 0);", + " }", + " else {", + " this._temp.set(-particle.velocity.y, particle.velocity.x, 0);", + " }", + " this._q.setFromAxisAngle(this._temp.normalize(), this.angle.genValue());", + " this._temp.copy(particle.velocity);", + " particle.velocity.applyQuaternion(this._q);", + " this._q.setFromAxisAngle(this._temp, Math.random() * Math.PI * 2);", + " particle.velocity.applyQuaternion(this._q);", + " particle.velocity.setLength(len);", + " }", + " update(particle, delta) {", + " }", + " frameUpdate(delta) {", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " angle: this.angle.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new ChangeEmitDirection(ValueGeneratorFromJSON(json.angle));", + " }", + " clone() {", + " return new ChangeEmitDirection(this.angle);", + " }", + " reset() {", + " }", + "}", + "", + "const VECTOR_ONE = new THREE.Vector3(1, 1, 1);", + "const VECTOR_Z = new THREE.Vector3(0, 0, 1);", + "let SubParticleEmitMode = void 0;", + "(function (SubParticleEmitMode) {", + " SubParticleEmitMode[SubParticleEmitMode[\"Death\"] = 0] = \"Death\";", + " SubParticleEmitMode[SubParticleEmitMode[\"Birth\"] = 1] = \"Birth\";", + " SubParticleEmitMode[SubParticleEmitMode[\"Frame\"] = 2] = \"Frame\";", + "})(SubParticleEmitMode || (SubParticleEmitMode = {}));", + "class EmitSubParticleSystem {", + " constructor(particleSystem, useVelocityAsBasis, subParticleSystem, mode = SubParticleEmitMode.Frame, emitProbability = 1) {", + " this.particleSystem = particleSystem;", + " this.useVelocityAsBasis = useVelocityAsBasis;", + " this.subParticleSystem = subParticleSystem;", + " this.mode = mode;", + " this.emitProbability = emitProbability;", + " this.type = 'EmitSubParticleSystem';", + " this.q_ = new THREE.Quaternion();", + " this.v_ = new THREE.Vector3();", + " this.v2_ = new THREE.Vector3();", + " this.subEmissions = new Array();", + " if (this.subParticleSystem && this.subParticleSystem.system) {", + " this.subParticleSystem.system.onlyUsedByOther = true;", + " }", + " }", + " initialize(particle) {", + " }", + " update(particle, delta) {", + " if (this.mode === SubParticleEmitMode.Frame) {", + " this.emit(particle, delta);", + " }", + " else if (this.mode === SubParticleEmitMode.Birth && particle.age === 0) {", + " this.emit(particle, delta);", + " }", + " else if (this.mode === SubParticleEmitMode.Death && particle.age + delta >= particle.life) {", + " this.emit(particle, delta);", + " }", + " }", + " emit(particle, delta) {", + " if (!this.subParticleSystem)", + " return;", + " if (Math.random() > this.emitProbability) {", + " return;", + " }", + " const m = new THREE.Matrix4();", + " this.setMatrixFromParticle(m, particle);", + " this.subEmissions.push({", + " burstIndex: 0,", + " burstWaveIndex: 0,", + " time: 0,", + " waitEmiting: 0,", + " matrix: m,", + " travelDistance: 0,", + " particle: particle,", + " });", + " }", + " frameUpdate(delta) {", + " if (!this.subParticleSystem)", + " return;", + " for (let i = 0; i < this.subEmissions.length; i++) {", + " if (this.subEmissions[i].time >= this.subParticleSystem.system.duration) {", + " this.subEmissions[i] = this.subEmissions[this.subEmissions.length - 1];", + " this.subEmissions.length = this.subEmissions.length - 1;", + " i--;", + " }", + " else {", + " let subEmissionState = this.subEmissions[i];", + " if (subEmissionState.particle && subEmissionState.particle.age < subEmissionState.particle.life) {", + " this.setMatrixFromParticle(subEmissionState.matrix, subEmissionState.particle);", + " }", + " else {", + " subEmissionState.particle = undefined;", + " }", + " this.subParticleSystem.system.emit(delta, subEmissionState, subEmissionState.matrix);", + " }", + " }", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " subParticleSystem: this.subParticleSystem ? this.subParticleSystem.uuid : '',", + " useVelocityAsBasis: this.useVelocityAsBasis,", + " mode: this.mode,", + " emitProbability: this.emitProbability,", + " };", + " }", + " static fromJSON(json, particleSystem) {", + " return new EmitSubParticleSystem(particleSystem, json.useVelocityAsBasis, json.subParticleSystem, json.mode, json.emitProbability);", + " }", + " clone() {", + " return new EmitSubParticleSystem(this.particleSystem, this.useVelocityAsBasis, this.subParticleSystem, this.mode, this.emitProbability);", + " }", + " reset() { }", + " setMatrixFromParticle(m, particle) {", + " let rotation;", + " if (particle.rotation === undefined || this.useVelocityAsBasis) {", + " if (particle.velocity.x === 0 &&", + " particle.velocity.y === 0 &&", + " (particle.velocity.z === 1 || particle.velocity.z === 0)) {", + " m.set(1, 0, 0, particle.position.x, 0, 1, 0, particle.position.y, 0, 0, 1, particle.position.z, 0, 0, 0, 1);", + " }", + " else {", + " this.v_.copy(VECTOR_Z).cross(particle.velocity);", + " this.v2_.copy(particle.velocity).cross(this.v_);", + " const len = this.v_.length();", + " const len2 = this.v2_.length();", + " m.set(this.v_.x / len, this.v2_.x / len2, particle.velocity.x, particle.position.x, this.v_.y / len, this.v2_.y / len2, particle.velocity.y, particle.position.y, this.v_.z / len, this.v2_.z / len2, particle.velocity.z, particle.position.z, 0, 0, 0, 1);", + " }", + " }", + " else {", + " if (particle.rotation instanceof THREE.Quaternion) {", + " rotation = particle.rotation;", + " }", + " else {", + " this.q_.setFromAxisAngle(VECTOR_Z, particle.rotation);", + " rotation = this.q_;", + " }", + " m.compose(particle.position, rotation, VECTOR_ONE);", + " }", + " if (!this.particleSystem.worldSpace) {", + " m.multiplyMatrices(this.particleSystem.emitter.matrixWorld, m);", + " }", + " }", + "}", + "", + "const F2 = 0.5 * (Math.sqrt(3.0) - 1.0);", + "const G2 = (3.0 - Math.sqrt(3.0)) / 6.0;", + "const F3 = 1.0 / 3.0;", + "const G3 = 1.0 / 6.0;", + "const F4 = (Math.sqrt(5.0) - 1.0) / 4.0;", + "const G4 = (5.0 - Math.sqrt(5.0)) / 20.0;", + "const grad3 = new Float32Array([1, 1, 0,", + " -1, 1, 0,", + " 1, -1, 0,", + " -1, -1, 0,", + " 1, 0, 1,", + " -1, 0, 1,", + " 1, 0, -1,", + " -1, 0, -1,", + " 0, 1, 1,", + " 0, -1, 1,", + " 0, 1, -1,", + " 0, -1, -1]);", + "const grad4 = new Float32Array([0, 1, 1, 1, 0, 1, 1, -1, 0, 1, -1, 1, 0, 1, -1, -1,", + " 0, -1, 1, 1, 0, -1, 1, -1, 0, -1, -1, 1, 0, -1, -1, -1,", + " 1, 0, 1, 1, 1, 0, 1, -1, 1, 0, -1, 1, 1, 0, -1, -1,", + " -1, 0, 1, 1, -1, 0, 1, -1, -1, 0, -1, 1, -1, 0, -1, -1,", + " 1, 1, 0, 1, 1, 1, 0, -1, 1, -1, 0, 1, 1, -1, 0, -1,", + " -1, 1, 0, 1, -1, 1, 0, -1, -1, -1, 0, 1, -1, -1, 0, -1,", + " 1, 1, 1, 0, 1, 1, -1, 0, 1, -1, 1, 0, 1, -1, -1, 0,", + " -1, 1, 1, 0, -1, 1, -1, 0, -1, -1, 1, 0, -1, -1, -1, 0]);", + "class SimplexNoise {", + " constructor(randomOrSeed = Math.random) {", + " const random = typeof randomOrSeed == 'function' ? randomOrSeed : alea(randomOrSeed);", + " this.p = buildPermutationTable(random);", + " this.perm = new Uint8Array(512);", + " this.permMod12 = new Uint8Array(512);", + " for (let i = 0; i < 512; i++) {", + " this.perm[i] = this.p[i & 255];", + " this.permMod12[i] = this.perm[i] % 12;", + " }", + " }", + " noise2D(x, y) {", + " const permMod12 = this.permMod12;", + " const perm = this.perm;", + " let n0 = 0;", + " let n1 = 0;", + " let n2 = 0;", + " const s = (x + y) * F2;", + " const i = Math.floor(x + s);", + " const j = Math.floor(y + s);", + " const t = (i + j) * G2;", + " const X0 = i - t;", + " const Y0 = j - t;", + " const x0 = x - X0;", + " const y0 = y - Y0;", + " let i1, j1;", + " if (x0 > y0) {", + " i1 = 1;", + " j1 = 0;", + " }", + " else {", + " i1 = 0;", + " j1 = 1;", + " }", + " const x1 = x0 - i1 + G2;", + " const y1 = y0 - j1 + G2;", + " const x2 = x0 - 1.0 + 2.0 * G2;", + " const y2 = y0 - 1.0 + 2.0 * G2;", + " const ii = i & 255;", + " const jj = j & 255;", + " let t0 = 0.5 - x0 * x0 - y0 * y0;", + " if (t0 >= 0) {", + " const gi0 = permMod12[ii + perm[jj]] * 3;", + " t0 *= t0;", + " n0 = t0 * t0 * (grad3[gi0] * x0 + grad3[gi0 + 1] * y0);", + " }", + " let t1 = 0.5 - x1 * x1 - y1 * y1;", + " if (t1 >= 0) {", + " const gi1 = permMod12[ii + i1 + perm[jj + j1]] * 3;", + " t1 *= t1;", + " n1 = t1 * t1 * (grad3[gi1] * x1 + grad3[gi1 + 1] * y1);", + " }", + " let t2 = 0.5 - x2 * x2 - y2 * y2;", + " if (t2 >= 0) {", + " const gi2 = permMod12[ii + 1 + perm[jj + 1]] * 3;", + " t2 *= t2;", + " n2 = t2 * t2 * (grad3[gi2] * x2 + grad3[gi2 + 1] * y2);", + " }", + " return 70.0 * (n0 + n1 + n2);", + " }", + " noise3D(x, y, z) {", + " const permMod12 = this.permMod12;", + " const perm = this.perm;", + " let n0, n1, n2, n3;", + " const s = (x + y + z) * F3;", + " const i = Math.floor(x + s);", + " const j = Math.floor(y + s);", + " const k = Math.floor(z + s);", + " const t = (i + j + k) * G3;", + " const X0 = i - t;", + " const Y0 = j - t;", + " const Z0 = k - t;", + " const x0 = x - X0;", + " const y0 = y - Y0;", + " const z0 = z - Z0;", + " let i1, j1, k1;", + " let i2, j2, k2;", + " if (x0 >= y0) {", + " if (y0 >= z0) {", + " i1 = 1;", + " j1 = 0;", + " k1 = 0;", + " i2 = 1;", + " j2 = 1;", + " k2 = 0;", + " }", + " else if (x0 >= z0) {", + " i1 = 1;", + " j1 = 0;", + " k1 = 0;", + " i2 = 1;", + " j2 = 0;", + " k2 = 1;", + " }", + " else {", + " i1 = 0;", + " j1 = 0;", + " k1 = 1;", + " i2 = 1;", + " j2 = 0;", + " k2 = 1;", + " }", + " }", + " else {", + " if (y0 < z0) {", + " i1 = 0;", + " j1 = 0;", + " k1 = 1;", + " i2 = 0;", + " j2 = 1;", + " k2 = 1;", + " }", + " else if (x0 < z0) {", + " i1 = 0;", + " j1 = 1;", + " k1 = 0;", + " i2 = 0;", + " j2 = 1;", + " k2 = 1;", + " }", + " else {", + " i1 = 0;", + " j1 = 1;", + " k1 = 0;", + " i2 = 1;", + " j2 = 1;", + " k2 = 0;", + " }", + " }", + " const x1 = x0 - i1 + G3;", + " const y1 = y0 - j1 + G3;", + " const z1 = z0 - k1 + G3;", + " const x2 = x0 - i2 + 2.0 * G3;", + " const y2 = y0 - j2 + 2.0 * G3;", + " const z2 = z0 - k2 + 2.0 * G3;", + " const x3 = x0 - 1.0 + 3.0 * G3;", + " const y3 = y0 - 1.0 + 3.0 * G3;", + " const z3 = z0 - 1.0 + 3.0 * G3;", + " const ii = i & 255;", + " const jj = j & 255;", + " const kk = k & 255;", + " let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;", + " if (t0 < 0)", + " n0 = 0.0;", + " else {", + " const gi0 = permMod12[ii + perm[jj + perm[kk]]] * 3;", + " t0 *= t0;", + " n0 = t0 * t0 * (grad3[gi0] * x0 + grad3[gi0 + 1] * y0 + grad3[gi0 + 2] * z0);", + " }", + " let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;", + " if (t1 < 0)", + " n1 = 0.0;", + " else {", + " const gi1 = permMod12[ii + i1 + perm[jj + j1 + perm[kk + k1]]] * 3;", + " t1 *= t1;", + " n1 = t1 * t1 * (grad3[gi1] * x1 + grad3[gi1 + 1] * y1 + grad3[gi1 + 2] * z1);", + " }", + " let t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;", + " if (t2 < 0)", + " n2 = 0.0;", + " else {", + " const gi2 = permMod12[ii + i2 + perm[jj + j2 + perm[kk + k2]]] * 3;", + " t2 *= t2;", + " n2 = t2 * t2 * (grad3[gi2] * x2 + grad3[gi2 + 1] * y2 + grad3[gi2 + 2] * z2);", + " }", + " let t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;", + " if (t3 < 0)", + " n3 = 0.0;", + " else {", + " const gi3 = permMod12[ii + 1 + perm[jj + 1 + perm[kk + 1]]] * 3;", + " t3 *= t3;", + " n3 = t3 * t3 * (grad3[gi3] * x3 + grad3[gi3 + 1] * y3 + grad3[gi3 + 2] * z3);", + " }", + " return 32.0 * (n0 + n1 + n2 + n3);", + " }", + " noise4D(x, y, z, w) {", + " const perm = this.perm;", + " let n0, n1, n2, n3, n4;", + " const s = (x + y + z + w) * F4;", + " const i = Math.floor(x + s);", + " const j = Math.floor(y + s);", + " const k = Math.floor(z + s);", + " const l = Math.floor(w + s);", + " const t = (i + j + k + l) * G4;", + " const X0 = i - t;", + " const Y0 = j - t;", + " const Z0 = k - t;", + " const W0 = l - t;", + " const x0 = x - X0;", + " const y0 = y - Y0;", + " const z0 = z - Z0;", + " const w0 = w - W0;", + " let rankx = 0;", + " let ranky = 0;", + " let rankz = 0;", + " let rankw = 0;", + " if (x0 > y0)", + " rankx++;", + " else", + " ranky++;", + " if (x0 > z0)", + " rankx++;", + " else", + " rankz++;", + " if (x0 > w0)", + " rankx++;", + " else", + " rankw++;", + " if (y0 > z0)", + " ranky++;", + " else", + " rankz++;", + " if (y0 > w0)", + " ranky++;", + " else", + " rankw++;", + " if (z0 > w0)", + " rankz++;", + " else", + " rankw++;", + " const i1 = rankx >= 3 ? 1 : 0;", + " const j1 = ranky >= 3 ? 1 : 0;", + " const k1 = rankz >= 3 ? 1 : 0;", + " const l1 = rankw >= 3 ? 1 : 0;", + " const i2 = rankx >= 2 ? 1 : 0;", + " const j2 = ranky >= 2 ? 1 : 0;", + " const k2 = rankz >= 2 ? 1 : 0;", + " const l2 = rankw >= 2 ? 1 : 0;", + " const i3 = rankx >= 1 ? 1 : 0;", + " const j3 = ranky >= 1 ? 1 : 0;", + " const k3 = rankz >= 1 ? 1 : 0;", + " const l3 = rankw >= 1 ? 1 : 0;", + " const x1 = x0 - i1 + G4;", + " const y1 = y0 - j1 + G4;", + " const z1 = z0 - k1 + G4;", + " const w1 = w0 - l1 + G4;", + " const x2 = x0 - i2 + 2.0 * G4;", + " const y2 = y0 - j2 + 2.0 * G4;", + " const z2 = z0 - k2 + 2.0 * G4;", + " const w2 = w0 - l2 + 2.0 * G4;", + " const x3 = x0 - i3 + 3.0 * G4;", + " const y3 = y0 - j3 + 3.0 * G4;", + " const z3 = z0 - k3 + 3.0 * G4;", + " const w3 = w0 - l3 + 3.0 * G4;", + " const x4 = x0 - 1.0 + 4.0 * G4;", + " const y4 = y0 - 1.0 + 4.0 * G4;", + " const z4 = z0 - 1.0 + 4.0 * G4;", + " const w4 = w0 - 1.0 + 4.0 * G4;", + " const ii = i & 255;", + " const jj = j & 255;", + " const kk = k & 255;", + " const ll = l & 255;", + " let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;", + " if (t0 < 0)", + " n0 = 0.0;", + " else {", + " const gi0 = (perm[ii + perm[jj + perm[kk + perm[ll]]]] % 32) * 4;", + " t0 *= t0;", + " n0 = t0 * t0 * (grad4[gi0] * x0 + grad4[gi0 + 1] * y0 + grad4[gi0 + 2] * z0 + grad4[gi0 + 3] * w0);", + " }", + " let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;", + " if (t1 < 0)", + " n1 = 0.0;", + " else {", + " const gi1 = (perm[ii + i1 + perm[jj + j1 + perm[kk + k1 + perm[ll + l1]]]] % 32) * 4;", + " t1 *= t1;", + " n1 = t1 * t1 * (grad4[gi1] * x1 + grad4[gi1 + 1] * y1 + grad4[gi1 + 2] * z1 + grad4[gi1 + 3] * w1);", + " }", + " let t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;", + " if (t2 < 0)", + " n2 = 0.0;", + " else {", + " const gi2 = (perm[ii + i2 + perm[jj + j2 + perm[kk + k2 + perm[ll + l2]]]] % 32) * 4;", + " t2 *= t2;", + " n2 = t2 * t2 * (grad4[gi2] * x2 + grad4[gi2 + 1] * y2 + grad4[gi2 + 2] * z2 + grad4[gi2 + 3] * w2);", + " }", + " let t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;", + " if (t3 < 0)", + " n3 = 0.0;", + " else {", + " const gi3 = (perm[ii + i3 + perm[jj + j3 + perm[kk + k3 + perm[ll + l3]]]] % 32) * 4;", + " t3 *= t3;", + " n3 = t3 * t3 * (grad4[gi3] * x3 + grad4[gi3 + 1] * y3 + grad4[gi3 + 2] * z3 + grad4[gi3 + 3] * w3);", + " }", + " let t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;", + " if (t4 < 0)", + " n4 = 0.0;", + " else {", + " const gi4 = (perm[ii + 1 + perm[jj + 1 + perm[kk + 1 + perm[ll + 1]]]] % 32) * 4;", + " t4 *= t4;", + " n4 = t4 * t4 * (grad4[gi4] * x4 + grad4[gi4 + 1] * y4 + grad4[gi4 + 2] * z4 + grad4[gi4 + 3] * w4);", + " }", + " return 27.0 * (n0 + n1 + n2 + n3 + n4);", + " }", + "}", + "function buildPermutationTable(random) {", + " const p = new Uint8Array(256);", + " for (let i = 0; i < 256; i++) {", + " p[i] = i;", + " }", + " for (let i = 0; i < 255; i++) {", + " const r = i + ~~(random() * (256 - i));", + " const aux = p[i];", + " p[i] = p[r];", + " p[r] = aux;", + " }", + " return p;", + "}", + "function alea(seed) {", + " let s0 = 0;", + " let s1 = 0;", + " let s2 = 0;", + " let c = 1;", + " const mash = masher();", + " s0 = mash(' ');", + " s1 = mash(' ');", + " s2 = mash(' ');", + " s0 -= mash(seed);", + " if (s0 < 0) {", + " s0 += 1;", + " }", + " s1 -= mash(seed);", + " if (s1 < 0) {", + " s1 += 1;", + " }", + " s2 -= mash(seed);", + " if (s2 < 0) {", + " s2 += 1;", + " }", + " return function () {", + " const t = 2091639 * s0 + c * 2.3283064365386963e-10;", + " s0 = s1;", + " s1 = s2;", + " return s2 = t - (c = t | 0);", + " };", + "}", + "function masher() {", + " let n = 0xefc8249d;", + " return function (data) {", + " data = data.toString();", + " for (let i = 0; i < data.length; i++) {", + " n += data.charCodeAt(i);", + " let h = 0.02519603282416938 * n;", + " n = h >>> 0;", + " h -= n;", + " h *= n;", + " n = h >>> 0;", + " h -= n;", + " n += h * 0x100000000;", + " }", + " return (n >>> 0) * 2.3283064365386963e-10;", + " };", + "}", + "", + "class TurbulenceField {", + " constructor(scale, octaves, velocityMultiplier, timeScale) {", + " this.scale = scale;", + " this.octaves = octaves;", + " this.velocityMultiplier = velocityMultiplier;", + " this.timeScale = timeScale;", + " this.type = 'TurbulenceField';", + " this.generator = new SimplexNoise();", + " this.timeOffset = new THREE.Vector3();", + " this.temp = new THREE.Vector3();", + " this.temp2 = new THREE.Vector3();", + " this.timeOffset.x = Math.random() / this.scale.x * this.timeScale.x;", + " this.timeOffset.y = Math.random() / this.scale.y * this.timeScale.y;", + " this.timeOffset.z = Math.random() / this.scale.z * this.timeScale.z;", + " }", + " initialize(particle) {", + " }", + " update(particle, delta) {", + " const x = particle.position.x / this.scale.x;", + " const y = particle.position.y / this.scale.y;", + " const z = particle.position.z / this.scale.z;", + " this.temp.set(0, 0, 0);", + " let lvl = 1;", + " for (let i = 0; i < this.octaves; i++) {", + " this.temp2.set(this.generator.noise4D(x * lvl, y * lvl, z * lvl, this.timeOffset.x * lvl) / lvl, this.generator.noise4D(x * lvl, y * lvl, z * lvl, this.timeOffset.y * lvl) / lvl, this.generator.noise4D(x * lvl, y * lvl, z * lvl, this.timeOffset.z * lvl) / lvl);", + " this.temp.add(this.temp2);", + " lvl *= 2;", + " }", + " this.temp.multiply(this.velocityMultiplier);", + " particle.velocity.addScaledVector(this.temp, delta);", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " scale: [this.scale.x, this.scale.y, this.scale.z],", + " octaves: this.octaves,", + " velocityMultiplier: [this.velocityMultiplier.x, this.velocityMultiplier.y, this.velocityMultiplier.z],", + " timeScale: [this.timeScale.x, this.timeScale.y, this.timeScale.z],", + " };", + " }", + " frameUpdate(delta) {", + " this.timeOffset.x += delta * this.timeScale.x;", + " this.timeOffset.y += delta * this.timeScale.y;", + " this.timeOffset.z += delta * this.timeScale.z;", + " }", + " static fromJSON(json) {", + " return new TurbulenceField(new THREE.Vector3(json.scale[0], json.scale[1], json.scale[2]), json.octaves, new THREE.Vector3(json.velocityMultiplier[0], json.velocityMultiplier[1], json.velocityMultiplier[2]), new THREE.Vector3(json.timeScale[0], json.timeScale[1], json.timeScale[2]));", + " }", + " clone() {", + " return new TurbulenceField(this.scale.clone(), this.octaves, this.velocityMultiplier.clone(), this.timeScale.clone());", + " }", + " reset() {", + " }", + "}", + "", + "function randomInt(a, b) {", + " return Math.floor(Math.random() * (b - a)) + a;", + "}", + "", + "const generators = [];", + "const tempV$2 = new THREE.Vector3();", + "const tempQ$2 = new THREE.Quaternion();", + "class Noise {", + " constructor(frequency, power, positionAmount = new ConstantValue(1), rotationAmount = new ConstantValue(0)) {", + " this.frequency = frequency;", + " this.power = power;", + " this.positionAmount = positionAmount;", + " this.rotationAmount = rotationAmount;", + " this.type = 'Noise';", + " this.duration = 0;", + " if (generators.length === 0) {", + " for (let i = 0; i < 100; i++) {", + " generators.push(new SimplexNoise());", + " }", + " }", + " }", + " initialize(particle) {", + " particle.lastPosNoise = new THREE.Vector3();", + " if (typeof particle.rotation === 'number') {", + " particle.lastRotNoise = 0;", + " }", + " else {", + " particle.lastRotNoise = new THREE.Quaternion();", + " }", + " particle.generatorIndex = [randomInt(0, 100), randomInt(0, 100), randomInt(0, 100), randomInt(0, 100)];", + " }", + " update(particle, _) {", + " let frequency = this.frequency.genValue(particle.age / particle.life);", + " let power = this.power.genValue(particle.age / particle.life);", + " let positionAmount = this.positionAmount.genValue(particle.age / particle.life);", + " let rotationAmount = this.rotationAmount.genValue(particle.age / particle.life);", + " if (positionAmount > 0 && particle.lastPosNoise !== undefined) {", + " particle.position.sub(particle.lastPosNoise);", + " tempV$2.set(generators[particle.generatorIndex[0]].noise2D(0, particle.age * frequency) *", + " power *", + " positionAmount, generators[particle.generatorIndex[1]].noise2D(0, particle.age * frequency) *", + " power *", + " positionAmount, generators[particle.generatorIndex[2]].noise2D(0, particle.age * frequency) *", + " power *", + " positionAmount);", + " particle.position.add(tempV$2);", + " particle.lastPosNoise.copy(tempV$2);", + " }", + " if (rotationAmount > 0 && particle.lastRotNoise !== undefined) {", + " if (typeof particle.rotation === 'number') {", + " particle.rotation -= particle.lastRotNoise;", + " particle.rotation +=", + " generators[particle.generatorIndex[3]].noise2D(0, particle.age * frequency) *", + " Math.PI *", + " power *", + " rotationAmount;", + " }", + " else {", + " particle.lastRotNoise.invert();", + " particle.rotation.multiply(particle.lastRotNoise);", + " tempQ$2", + " .set(generators[particle.generatorIndex[0]].noise2D(0, particle.age * frequency) *", + " power *", + " rotationAmount, generators[particle.generatorIndex[1]].noise2D(0, particle.age * frequency) *", + " power *", + " rotationAmount, generators[particle.generatorIndex[2]].noise2D(0, particle.age * frequency) *", + " power *", + " rotationAmount, generators[particle.generatorIndex[3]].noise2D(0, particle.age * frequency) *", + " power *", + " rotationAmount)", + " .normalize();", + " particle.rotation.multiply(tempQ$2);", + " particle.lastRotNoise.copy(tempQ$2);", + " }", + " }", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " frequency: this.frequency.toJSON(),", + " power: this.power.toJSON(),", + " positionAmount: this.positionAmount.toJSON(),", + " rotationAmount: this.rotationAmount.toJSON(),", + " };", + " }", + " frameUpdate(delta) {", + " this.duration += delta;", + " }", + " static fromJSON(json) {", + " return new Noise(ValueGeneratorFromJSON(json.frequency), ValueGeneratorFromJSON(json.power), ValueGeneratorFromJSON(json.positionAmount), ValueGeneratorFromJSON(json.rotationAmount));", + " }", + " clone() {", + " return new Noise(this.frequency.clone(), this.power.clone(), this.positionAmount.clone(), this.rotationAmount.clone());", + " }", + " reset() { }", + "}", + "", + "class TextureSequencer {", + " constructor(scaleX = 0, scaleY = 0, position = new THREE.Vector3()) {", + " this.scaleX = scaleX;", + " this.scaleY = scaleY;", + " this.position = position;", + " this.locations = [];", + " }", + " transform(position, index) {", + " position.x = this.locations[index % this.locations.length].x * this.scaleX + this.position.x;", + " position.y = this.locations[index % this.locations.length].y * this.scaleY + this.position.y;", + " position.z = this.position.z;", + " }", + " static fromJSON(json) {", + " const textureSequencer = new TextureSequencer(json.scaleX, json.scaleY, new THREE.Vector3(json.position[0], json.position[1], json.position[2]));", + " textureSequencer.locations = json.locations.map((loc) => new THREE.Vector2(loc.x, loc.y));", + " return textureSequencer;", + " }", + " clone() {", + " const textureSequencer = new TextureSequencer(this.scaleX, this.scaleY, this.position.clone());", + " textureSequencer.locations = this.locations.map(loc => loc.clone());", + " return textureSequencer;", + " }", + " toJSON() {", + " return {", + " scaleX: this.scaleX,", + " scaleY: this.scaleY,", + " position: this.position,", + " locations: this.locations.map(loc => ({", + " x: loc.x,", + " y: loc.y,", + " }))", + " };", + " }", + " fromImage(img, threshold) {", + " const canvas = document.createElement(\"canvas\");", + " canvas.width = img.width;", + " canvas.height = img.height;", + " const ctx = canvas.getContext(\"2d\");", + " if (!ctx) {", + " return;", + " }", + " ctx.drawImage(img, 0, 0);", + " const data = ctx.getImageData(0, 0, canvas.width, canvas.height, { colorSpace: \"srgb\" });", + " canvas.remove();", + " this.locations.length = 0;", + " for (let i = 0; i < data.height; i++) {", + " for (let j = 0; j < data.width; j++) {", + " if (data.data[(i * data.width + j) * 4 + 3] > threshold) {", + " this.locations.push(new THREE.Vector2(j, data.height - i));", + " }", + " }", + " }", + " }", + "}", + "", + "function SequencerFromJSON(json) {", + " switch (json.type) {", + " case 'TextureSequencer':", + " return TextureSequencer.fromJSON(json);", + " default:", + " return new TextureSequencer();", + " }", + "}", + "", + "class ApplySequences {", + " constructor(delayBetweenParticles) {", + " this.type = 'ApplySequences';", + " this.sequencers = [];", + " this.time = 0;", + " this.index = 0;", + " this.pCount = 0;", + " this.tempV = new THREE.Vector3();", + " this.delay = delayBetweenParticles;", + " }", + " initialize(particle) {", + " particle.id = this.pCount;", + " particle.dst = new THREE.Vector3();", + " particle.begin = new THREE.Vector3();", + " particle.inMotion = false;", + " this.pCount++;", + " }", + " reset() {", + " this.time = 0;", + " this.index = 0;", + " this.pCount = 0;", + " }", + " update(particle, delta) {", + " const sequencer = this.sequencers[this.index];", + " const delay = particle.id * this.delay;", + " if (this.time >= sequencer[0].a + delay && this.time <= sequencer[0].b + delay) {", + " if (!particle.inMotion) {", + " particle.inMotion = true;", + " particle.begin.copy(particle.position);", + " sequencer[1].transform(particle.dst, particle.id);", + " }", + " particle.position.lerpVectors(particle.begin, particle.dst, ApplySequences.BEZIER.genValue((this.time - sequencer[0].a - delay) / (sequencer[0].b - sequencer[0].a)));", + " }", + " else if (this.time > sequencer[0].b + delay) {", + " particle.inMotion = false;", + " }", + " }", + " frameUpdate(delta) {", + " while (this.index + 1 < this.sequencers.length && this.time >= this.sequencers[this.index + 1][0].a) {", + " this.index++;", + " }", + " this.time += delta;", + " }", + " appendSequencer(range, sequencer) {", + " this.sequencers.push([range, sequencer]);", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " delay: this.delay,", + " sequencers: this.sequencers.map(([range, sequencer]) => ({", + " range: range.toJSON(),", + " sequencer: sequencer.toJSON(),", + " })),", + " };", + " }", + " static fromJSON(json) {", + " const seq = new ApplySequences(json.delay);", + " json.sequencers.forEach((sequencerJson) => {", + " seq.sequencers.push([ValueGeneratorFromJSON(sequencerJson.range), SequencerFromJSON(sequencerJson.sequencer)]);", + " });", + " return seq;", + " }", + " clone() {", + " const applySequences = new ApplySequences(this.delay);", + " applySequences.sequencers = this.sequencers.map(seq => [seq[0].clone(), seq[1].clone()]);", + " return applySequences;", + " }", + "}", + "ApplySequences.BEZIER = new Bezier(0, 0, 1, 1);", + "", + "let physicsResolver;", + "function setPhysicsResolver(resolver) {", + " physicsResolver = resolver;", + "}", + "function getPhysicsResolver() {", + " return physicsResolver;", + "}", + "class ApplyCollision {", + " constructor(resolver, bounce) {", + " this.resolver = resolver;", + " this.bounce = bounce;", + " this.type = 'ApplyCollision';", + " this.tempV = new THREE.Vector3();", + " }", + " initialize(particle) {", + " }", + " update(particle, delta) {", + " if (this.resolver.resolve(particle.position, this.tempV)) {", + " particle.velocity.reflect(this.tempV).multiplyScalar(this.bounce);", + " }", + " }", + " frameUpdate(delta) {", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " bounce: this.bounce,", + " };", + " }", + " static fromJSON(json) {", + " return new ApplyCollision(getPhysicsResolver(), json.bounce);", + " }", + " clone() {", + " return new ApplyCollision(this.resolver, this.bounce);", + " }", + " reset() {", + " }", + "}", + "", + "class ColorBySpeed {", + " constructor(color, speedRange) {", + " this.color = color;", + " this.speedRange = speedRange;", + " this.type = 'ColorBySpeed';", + " }", + " initialize(particle) {", + " if (this.color.type === 'memorizedFunction') {", + " particle.colorOverLifeMemory = {};", + " this.color.startGen(particle.colorOverLifeMemory);", + " }", + " }", + " update(particle, delta) {", + " const t = (particle.startSpeed - this.speedRange.a) / (this.speedRange.b - this.speedRange.a);", + " if (this.color.type === 'memorizedFunction') {", + " this.color.genColor(particle.color, t, particle.colorOverLifeMemory);", + " }", + " else {", + " this.color.genColor(particle.color, t);", + " }", + " particle.color.x *= particle.startColor.x;", + " particle.color.y *= particle.startColor.y;", + " particle.color.z *= particle.startColor.z;", + " particle.color.w *= particle.startColor.w;", + " }", + " frameUpdate(delta) { }", + " toJSON() {", + " return {", + " type: this.type,", + " color: this.color.toJSON(),", + " speedRange: this.speedRange.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new ColorBySpeed(ColorGeneratorFromJSON(json.color), IntervalValue.fromJSON(json.speedRange));", + " }", + " clone() {", + " return new ColorBySpeed(this.color.clone(), this.speedRange.clone());", + " }", + " reset() { }", + "}", + "", + "class SizeBySpeed {", + " initialize(particle) { }", + " constructor(size, speedRange) {", + " this.size = size;", + " this.speedRange = speedRange;", + " this.type = 'SizeBySpeed';", + " }", + " update(particle) {", + " const t = (particle.startSpeed - this.speedRange.a) / (this.speedRange.b - this.speedRange.a);", + " particle.size = particle.startSize * this.size.genValue(t);", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " size: this.size.toJSON(),", + " speedRange: this.speedRange.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new SizeBySpeed(ValueGeneratorFromJSON(json.size), IntervalValue.fromJSON(json.speedRange));", + " }", + " frameUpdate(delta) { }", + " clone() {", + " return new SizeBySpeed(this.size.clone(), this.speedRange.clone());", + " }", + " reset() { }", + "}", + "", + "class RotationBySpeed {", + " constructor(angularVelocity, speedRange) {", + " this.angularVelocity = angularVelocity;", + " this.speedRange = speedRange;", + " this.type = 'RotationBySpeed';", + " this.tempQuat = new THREE.Quaternion();", + " }", + " initialize(particle) { }", + " update(particle, delta) {", + " const t = (particle.startSpeed - this.speedRange.a) / (this.speedRange.b - this.speedRange.a);", + " particle.rotation += delta * this.angularVelocity.genValue(t);", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " angularVelocity: this.angularVelocity.toJSON(),", + " speedRange: this.speedRange.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new RotationBySpeed(ValueGeneratorFromJSON(json.angularVelocity), IntervalValue.fromJSON(json.speedRange));", + " }", + " frameUpdate(delta) { }", + " clone() {", + " return new RotationBySpeed(this.angularVelocity.clone(), this.speedRange.clone());", + " }", + " reset() { }", + "}", + "", + "class LimitSpeedOverLife {", + " initialize(particle) { }", + " constructor(speed, dampen) {", + " this.speed = speed;", + " this.dampen = dampen;", + " this.type = 'LimitSpeedOverLife';", + " }", + " update(particle, delta) {", + " let speed = particle.velocity.length();", + " let limit = this.speed.genValue(particle.age / particle.life);", + " if (speed > limit) {", + " const percent = (speed - limit) / speed;", + " particle.velocity.multiplyScalar(1 - percent * this.dampen * delta * 20);", + " }", + " }", + " toJSON() {", + " return {", + " type: this.type,", + " speed: this.speed.toJSON(),", + " dampen: this.dampen,", + " };", + " }", + " static fromJSON(json) {", + " return new LimitSpeedOverLife(ValueGeneratorFromJSON(json.speed), json.dampen);", + " }", + " frameUpdate(delta) { }", + " clone() {", + " return new LimitSpeedOverLife(this.speed.clone(), this.dampen);", + " }", + " reset() { }", + "}", + "", + "const BehaviorTypes = {", + " ApplyForce: {", + " type: 'ApplyForce',", + " constructor: ApplyForce,", + " params: [", + " ['direction', 'vec3'],", + " ['magnitude', 'value'],", + " ],", + " loadJSON: ApplyForce.fromJSON,", + " },", + " Noise: {", + " type: 'Noise',", + " constructor: Noise,", + " params: [", + " ['frequency', 'value'],", + " ['power', 'value'],", + " ['positionAmount', 'value'],", + " ['rotationAmount', 'value'],", + " ],", + " loadJSON: Noise.fromJSON,", + " },", + " TurbulenceField: {", + " type: 'TurbulenceField',", + " constructor: TurbulenceField,", + " params: [", + " ['scale', 'vec3'],", + " ['octaves', 'number'],", + " ['velocityMultiplier', 'vec3'],", + " ['timeScale', 'vec3'],", + " ],", + " loadJSON: TurbulenceField.fromJSON,", + " },", + " GravityForce: {", + " type: 'GravityForce',", + " constructor: GravityForce,", + " params: [", + " ['center', 'vec3'],", + " ['magnitude', 'number'],", + " ],", + " loadJSON: GravityForce.fromJSON,", + " },", + " ColorOverLife: {", + " type: 'ColorOverLife',", + " constructor: ColorOverLife,", + " params: [['color', 'colorFunc']],", + " loadJSON: ColorOverLife.fromJSON,", + " },", + " RotationOverLife: {", + " type: 'RotationOverLife',", + " constructor: RotationOverLife,", + " params: [['angularVelocity', 'valueFunc']],", + " loadJSON: RotationOverLife.fromJSON,", + " },", + " Rotation3DOverLife: {", + " type: 'Rotation3DOverLife',", + " constructor: Rotation3DOverLife,", + " params: [['angularVelocity', 'rotationFunc']],", + " loadJSON: Rotation3DOverLife.fromJSON,", + " },", + " SizeOverLife: {", + " type: 'SizeOverLife',", + " constructor: SizeOverLife,", + " params: [['size', 'valueFunc']],", + " loadJSON: SizeOverLife.fromJSON,", + " },", + " ColorBySpeed: {", + " type: 'ColorBySpeed',", + " constructor: ColorBySpeed,", + " params: [", + " ['color', 'colorFunc'],", + " ['speedRange', 'range'],", + " ],", + " loadJSON: ColorBySpeed.fromJSON,", + " },", + " RotationBySpeed: {", + " type: 'RotationBySpeed',", + " constructor: RotationBySpeed,", + " params: [", + " ['angularVelocity', 'valueFunc'],", + " ['speedRange', 'range'],", + " ],", + " loadJSON: RotationBySpeed.fromJSON,", + " },", + " SizeBySpeed: {", + " type: 'SizeBySpeed',", + " constructor: SizeBySpeed,", + " params: [", + " ['size', 'valueFunc'],", + " ['speedRange', 'range'],", + " ],", + " loadJSON: SizeBySpeed.fromJSON,", + " },", + " SpeedOverLife: {", + " type: 'SpeedOverLife',", + " constructor: SpeedOverLife,", + " params: [['speed', 'valueFunc']],", + " loadJSON: SpeedOverLife.fromJSON,", + " },", + " FrameOverLife: {", + " type: 'FrameOverLife',", + " constructor: FrameOverLife,", + " params: [['frame', 'valueFunc']],", + " loadJSON: FrameOverLife.fromJSON,", + " },", + " ForceOverLife: {", + " type: 'ForceOverLife',", + " constructor: ForceOverLife,", + " params: [", + " ['x', 'valueFunc'],", + " ['y', 'valueFunc'],", + " ['z', 'valueFunc'],", + " ],", + " loadJSON: ForceOverLife.fromJSON,", + " },", + " OrbitOverLife: {", + " type: 'OrbitOverLife',", + " constructor: OrbitOverLife,", + " params: [", + " ['orbitSpeed', 'valueFunc'],", + " ['axis', 'vec3'],", + " ],", + " loadJSON: OrbitOverLife.fromJSON,", + " },", + " WidthOverLength: {", + " type: 'WidthOverLength',", + " constructor: WidthOverLength,", + " params: [['width', 'valueFunc']],", + " loadJSON: WidthOverLength.fromJSON,", + " },", + " ChangeEmitDirection: {", + " type: 'ChangeEmitDirection',", + " constructor: ChangeEmitDirection,", + " params: [['angle', 'value']],", + " loadJSON: ChangeEmitDirection.fromJSON,", + " },", + " EmitSubParticleSystem: {", + " type: 'EmitSubParticleSystem',", + " constructor: EmitSubParticleSystem,", + " params: [", + " ['particleSystem', 'self'],", + " ['useVelocityAsBasis', 'boolean'],", + " ['subParticleSystem', 'particleSystem'],", + " ['mode', 'number'],", + " ['emitProbability', 'number'],", + " ],", + " loadJSON: EmitSubParticleSystem.fromJSON,", + " },", + " LimitSpeedOverLife: {", + " type: 'LimitSpeedOverLife',", + " constructor: LimitSpeedOverLife,", + " params: [", + " ['speed', 'valueFunc'],", + " ['dampen', 'number'],", + " ],", + " loadJSON: LimitSpeedOverLife.fromJSON,", + " },", + "};", + "function BehaviorFromJSON(json, particleSystem) {", + " return BehaviorTypes[json.type].loadJSON(json, particleSystem);", + "}", + "", + "let EmitterMode = void 0;", + "(function (EmitterMode) {", + " EmitterMode[EmitterMode[\"Random\"] = 0] = \"Random\";", + " EmitterMode[EmitterMode[\"Loop\"] = 1] = \"Loop\";", + " EmitterMode[EmitterMode[\"PingPong\"] = 2] = \"PingPong\";", + " EmitterMode[EmitterMode[\"Burst\"] = 3] = \"Burst\";", + "})(EmitterMode || (EmitterMode = {}));", + "function getValueFromEmitterMode(mode, currentValue, spread) {", + " let u;", + " if (EmitterMode.Random === mode) {", + " currentValue = Math.random();", + " }", + " if (spread > 0) {", + " u = Math.floor(currentValue / spread) * spread;", + " }", + " else {", + " u = currentValue;", + " }", + " switch (mode) {", + " case EmitterMode.Loop:", + " u = u % 1;", + " break;", + " case EmitterMode.PingPong:", + " u = Math.abs((u % 2) - 1);", + " break;", + " }", + " return u;", + "}", + "", + "class ConeEmitter {", + " constructor(parameters = {}) {", + " var _a, _b, _c, _d, _e, _f, _g;", + " this.type = 'cone';", + " this.currentValue = 0;", + " this.radius = (_a = parameters.radius) !== null && _a !== void 0 ? _a : 10;", + " this.arc = (_b = parameters.arc) !== null && _b !== void 0 ? _b : 2.0 * Math.PI;", + " this.thickness = (_c = parameters.thickness) !== null && _c !== void 0 ? _c : 1;", + " this.angle = (_d = parameters.angle) !== null && _d !== void 0 ? _d : Math.PI / 6;", + " this.mode = (_e = parameters.mode) !== null && _e !== void 0 ? _e : EmitterMode.Random;", + " this.spread = (_f = parameters.spread) !== null && _f !== void 0 ? _f : 0;", + " this.speed = (_g = parameters.speed) !== null && _g !== void 0 ? _g : new ConstantValue(1);", + " }", + " update(system, delta) {", + " if (EmitterMode.Random != this.mode) {", + " this.currentValue += this.speed.genValue(system.emissionState.time / system.duration) * delta;", + " }", + " }", + " initialize(p) {", + " const u = getValueFromEmitterMode(this.mode, this.currentValue, this.spread);", + " const rand = THREE.MathUtils.lerp(1 - this.thickness, 1, Math.random());", + " const theta = u * this.arc;", + " const r = Math.sqrt(rand);", + " const sinTheta = Math.sin(theta);", + " const cosTheta = Math.cos(theta);", + " p.position.x = r * cosTheta;", + " p.position.y = r * sinTheta;", + " p.position.z = 0;", + " const angle = this.angle * r;", + " p.velocity.set(0, 0, Math.cos(angle)).addScaledVector(p.position, Math.sin(angle)).multiplyScalar(p.startSpeed);", + " p.position.multiplyScalar(this.radius);", + " }", + " toJSON() {", + " return {", + " type: 'cone',", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " angle: this.angle,", + " mode: this.mode,", + " spread: this.spread,", + " speed: this.speed.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new ConeEmitter({", + " radius: json.radius,", + " arc: json.arc,", + " thickness: json.thickness,", + " angle: json.angle,", + " mode: json.mode,", + " speed: json.speed ? ValueGeneratorFromJSON(json.speed) : undefined,", + " spread: json.spread,", + " });", + " }", + " clone() {", + " return new ConeEmitter({", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " angle: this.angle,", + " mode: this.mode,", + " speed: this.speed.clone(),", + " spread: this.spread,", + " });", + " }", + "}", + "", + "class CircleEmitter {", + " constructor(parameters = {}) {", + " var _a, _b, _c, _d, _e, _f;", + " this.type = 'circle';", + " this.currentValue = 0;", + " this.radius = (_a = parameters.radius) !== null && _a !== void 0 ? _a : 10;", + " this.arc = (_b = parameters.arc) !== null && _b !== void 0 ? _b : 2.0 * Math.PI;", + " this.thickness = (_c = parameters.thickness) !== null && _c !== void 0 ? _c : 1;", + " this.mode = (_d = parameters.mode) !== null && _d !== void 0 ? _d : EmitterMode.Random;", + " this.spread = (_e = parameters.spread) !== null && _e !== void 0 ? _e : 0;", + " this.speed = (_f = parameters.speed) !== null && _f !== void 0 ? _f : new ConstantValue(1);", + " }", + " update(system, delta) {", + " this.currentValue += this.speed.genValue(system.emissionState.time / system.duration) * delta;", + " }", + " initialize(p) {", + " const u = getValueFromEmitterMode(this.mode, this.currentValue, this.spread);", + " const r = THREE.MathUtils.lerp(1 - this.thickness, 1, Math.random());", + " const theta = u * this.arc;", + " p.position.x = Math.cos(theta);", + " p.position.y = Math.sin(theta);", + " p.position.z = 0;", + " p.velocity.copy(p.position).multiplyScalar(p.startSpeed);", + " p.position.multiplyScalar(this.radius * r);", + " }", + " toJSON() {", + " return {", + " type: 'circle',", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " mode: this.mode,", + " spread: this.spread,", + " speed: this.speed.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new CircleEmitter({", + " radius: json.radius,", + " arc: json.arc,", + " thickness: json.thickness,", + " mode: json.mode,", + " speed: json.speed ? ValueGeneratorFromJSON(json.speed) : undefined,", + " spread: json.spread,", + " });", + " }", + " clone() {", + " return new CircleEmitter({", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " mode: this.mode,", + " speed: this.speed.clone(),", + " spread: this.spread,", + " });", + " }", + "}", + "", + "class DonutEmitter {", + " constructor(parameters = {}) {", + " var _a, _b, _c, _d, _e, _f, _g;", + " this.type = 'donut';", + " this.currentValue = 0;", + " this.radius = (_a = parameters.radius) !== null && _a !== void 0 ? _a : 10;", + " this.arc = (_b = parameters.arc) !== null && _b !== void 0 ? _b : 2.0 * Math.PI;", + " this.thickness = (_c = parameters.thickness) !== null && _c !== void 0 ? _c : 1;", + " this.donutRadius = (_d = parameters.donutRadius) !== null && _d !== void 0 ? _d : this.radius * 0.2;", + " this.mode = (_e = parameters.mode) !== null && _e !== void 0 ? _e : EmitterMode.Random;", + " this.spread = (_f = parameters.spread) !== null && _f !== void 0 ? _f : 0;", + " this.speed = (_g = parameters.speed) !== null && _g !== void 0 ? _g : new ConstantValue(1);", + " }", + " update(system, delta) {", + " if (EmitterMode.Random != this.mode) {", + " this.currentValue += this.speed.genValue(system.emissionState.time / system.duration) * delta;", + " }", + " }", + " initialize(p) {", + " const u = getValueFromEmitterMode(this.mode, this.currentValue, this.spread);", + " const v = Math.random();", + " const rand = THREE.MathUtils.lerp(1 - this.thickness, 1, Math.random());", + " const theta = u * this.arc;", + " const phi = v * Math.PI * 2;", + " const sinTheta = Math.sin(theta);", + " const cosTheta = Math.cos(theta);", + " p.position.x = this.radius * cosTheta;", + " p.position.y = this.radius * sinTheta;", + " p.position.z = 0;", + " p.velocity.z = this.donutRadius * rand * Math.sin(phi);", + " p.velocity.x = this.donutRadius * rand * Math.cos(phi) * cosTheta;", + " p.velocity.y = this.donutRadius * rand * Math.cos(phi) * sinTheta;", + " p.position.add(p.velocity);", + " p.velocity.normalize().multiplyScalar(p.startSpeed);", + " }", + " toJSON() {", + " return {", + " type: 'donut',", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " donutRadius: this.donutRadius,", + " mode: this.mode,", + " spread: this.spread,", + " speed: this.speed.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new DonutEmitter({", + " radius: json.radius,", + " arc: json.arc,", + " thickness: json.thickness,", + " donutRadius: json.donutRadius,", + " mode: json.mode,", + " speed: json.speed ? ValueGeneratorFromJSON(json.speed) : undefined,", + " spread: json.spread,", + " });", + " }", + " clone() {", + " return new DonutEmitter({", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " donutRadius: this.donutRadius,", + " mode: this.mode,", + " speed: this.speed.clone(),", + " spread: this.spread,", + " });", + " }", + "}", + "", + "class PointEmitter {", + " constructor() {", + " this.type = 'point';", + " }", + " update(system, delta) { }", + " initialize(p) {", + " const u = Math.random();", + " const v = Math.random();", + " const theta = u * Math.PI * 2;", + " const phi = Math.acos(2.0 * v - 1.0);", + " const r = Math.cbrt(Math.random());", + " const sinTheta = Math.sin(theta);", + " const cosTheta = Math.cos(theta);", + " const sinPhi = Math.sin(phi);", + " const cosPhi = Math.cos(phi);", + " p.velocity.x = r * sinPhi * cosTheta;", + " p.velocity.y = r * sinPhi * sinTheta;", + " p.velocity.z = r * cosPhi;", + " p.velocity.multiplyScalar(p.startSpeed);", + " p.position.setScalar(0);", + " }", + " toJSON() {", + " return {", + " type: 'point',", + " };", + " }", + " static fromJSON(json) {", + " return new PointEmitter();", + " }", + " clone() {", + " return new PointEmitter();", + " }", + "}", + "", + "class SphereEmitter {", + " constructor(parameters = {}) {", + " var _a, _b, _c, _d, _e, _f;", + " this.type = 'sphere';", + " this.currentValue = 0;", + " this.radius = (_a = parameters.radius) !== null && _a !== void 0 ? _a : 10;", + " this.arc = (_b = parameters.arc) !== null && _b !== void 0 ? _b : 2.0 * Math.PI;", + " this.thickness = (_c = parameters.thickness) !== null && _c !== void 0 ? _c : 1;", + " this.mode = (_d = parameters.mode) !== null && _d !== void 0 ? _d : EmitterMode.Random;", + " this.spread = (_e = parameters.spread) !== null && _e !== void 0 ? _e : 0;", + " this.speed = (_f = parameters.speed) !== null && _f !== void 0 ? _f : new ConstantValue(1);", + " }", + " update(system, delta) {", + " if (EmitterMode.Random != this.mode) {", + " this.currentValue += this.speed.genValue(system.emissionState.time / system.duration) * delta;", + " }", + " }", + " initialize(p) {", + " const u = getValueFromEmitterMode(this.mode, this.currentValue, this.spread);", + " const v = Math.random();", + " const rand = THREE.MathUtils.lerp(1 - this.thickness, 1, Math.random());", + " const theta = u * this.arc;", + " const phi = Math.acos(2.0 * v - 1.0);", + " const sinTheta = Math.sin(theta);", + " const cosTheta = Math.cos(theta);", + " const sinPhi = Math.sin(phi);", + " const cosPhi = Math.cos(phi);", + " p.position.x = sinPhi * cosTheta;", + " p.position.y = sinPhi * sinTheta;", + " p.position.z = cosPhi;", + " p.velocity.copy(p.position).multiplyScalar(p.startSpeed);", + " p.position.multiplyScalar(this.radius * rand);", + " }", + " toJSON() {", + " return {", + " type: 'sphere',", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " mode: this.mode,", + " spread: this.spread,", + " speed: this.speed.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new SphereEmitter({", + " radius: json.radius,", + " arc: json.arc,", + " thickness: json.thickness,", + " mode: json.mode,", + " speed: json.speed ? ValueGeneratorFromJSON(json.speed) : undefined,", + " spread: json.spread,", + " });", + " }", + " clone() {", + " return new SphereEmitter({", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " mode: this.mode,", + " speed: this.speed.clone(),", + " spread: this.spread,", + " });", + " }", + "}", + "", + "class HemisphereEmitter {", + " constructor(parameters = {}) {", + " var _a, _b, _c, _d, _e, _f;", + " this.type = 'sphere';", + " this.currentValue = 0;", + " this.radius = (_a = parameters.radius) !== null && _a !== void 0 ? _a : 10;", + " this.arc = (_b = parameters.arc) !== null && _b !== void 0 ? _b : 2.0 * Math.PI;", + " this.thickness = (_c = parameters.thickness) !== null && _c !== void 0 ? _c : 1;", + " this.mode = (_d = parameters.mode) !== null && _d !== void 0 ? _d : EmitterMode.Random;", + " this.spread = (_e = parameters.spread) !== null && _e !== void 0 ? _e : 0;", + " this.speed = (_f = parameters.speed) !== null && _f !== void 0 ? _f : new ConstantValue(1);", + " }", + " update(system, delta) {", + " if (EmitterMode.Random != this.mode) {", + " this.currentValue += this.speed.genValue(system.emissionState.time / system.duration) * delta;", + " }", + " }", + " initialize(p) {", + " const u = getValueFromEmitterMode(this.mode, this.currentValue, this.spread);", + " const v = Math.random();", + " const rand = THREE.MathUtils.lerp(1 - this.thickness, 1, Math.random());", + " const theta = u * this.arc;", + " const phi = Math.acos(v);", + " const sinTheta = Math.sin(theta);", + " const cosTheta = Math.cos(theta);", + " const sinPhi = Math.sin(phi);", + " const cosPhi = Math.cos(phi);", + " p.position.x = sinPhi * cosTheta;", + " p.position.y = sinPhi * sinTheta;", + " p.position.z = cosPhi;", + " p.velocity.copy(p.position).multiplyScalar(p.startSpeed);", + " p.position.multiplyScalar(this.radius * rand);", + " }", + " toJSON() {", + " return {", + " type: 'hemisphere',", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " mode: this.mode,", + " spread: this.spread,", + " speed: this.speed.toJSON(),", + " };", + " }", + " static fromJSON(json) {", + " return new HemisphereEmitter({", + " radius: json.radius,", + " arc: json.arc,", + " thickness: json.thickness,", + " mode: json.mode,", + " speed: json.speed ? ValueGeneratorFromJSON(json.speed) : undefined,", + " spread: json.spread,", + " });", + " }", + " clone() {", + " return new HemisphereEmitter({", + " radius: this.radius,", + " arc: this.arc,", + " thickness: this.thickness,", + " mode: this.mode,", + " speed: this.speed.clone(),", + " spread: this.spread,", + " });", + " }", + "}", + "", + "class GridEmitter {", + " constructor(parameters = {}) {", + " var _a, _b, _c, _d;", + " this.type = 'grid';", + " this.width = (_a = parameters.width) !== null && _a !== void 0 ? _a : 1;", + " this.height = (_b = parameters.height) !== null && _b !== void 0 ? _b : 1;", + " this.column = (_c = parameters.column) !== null && _c !== void 0 ? _c : 10;", + " this.row = (_d = parameters.row) !== null && _d !== void 0 ? _d : 10;", + " }", + " initialize(p) {", + " const r = Math.floor(Math.random() * this.row);", + " const c = Math.floor(Math.random() * this.column);", + " p.position.x = (c * this.width) / this.column - this.width / 2;", + " p.position.y = (r * this.height) / this.row - this.height / 2;", + " p.position.z = 0;", + " p.velocity.set(0, 0, p.startSpeed);", + " }", + " toJSON() {", + " return {", + " type: 'grid',", + " width: this.width,", + " height: this.height,", + " column: this.column,", + " row: this.row,", + " };", + " }", + " static fromJSON(json) {", + " return new GridEmitter(json);", + " }", + " clone() {", + " return new GridEmitter({", + " width: this.width,", + " height: this.height,", + " column: this.column,", + " row: this.row,", + " });", + " }", + " update(system, delta) { }", + "}", + "", + "class MeshSurfaceEmitter {", + " get geometry() {", + " return this._geometry;", + " }", + " set geometry(geometry) {", + " this._geometry = geometry;", + " if (geometry === undefined) {", + " return;", + " }", + " if (typeof geometry === 'string') {", + " return;", + " }", + " const tri = new THREE.Triangle();", + " this._triangleIndexToArea.length = 0;", + " let area = 0;", + " if (!geometry.getIndex()) {", + " return;", + " }", + " const array = geometry.getIndex().array;", + " const triCount = array.length / 3;", + " this._triangleIndexToArea.push(0);", + " for (let i = 0; i < triCount; i++) {", + " tri.setFromAttributeAndIndices(geometry.getAttribute('position'), array[i * 3], array[i * 3 + 1], array[i * 3 + 2]);", + " area += tri.getArea();", + " this._triangleIndexToArea.push(area);", + " }", + " geometry.userData.triangleIndexToArea = this._triangleIndexToArea;", + " }", + " constructor(geometry) {", + " this.type = 'mesh_surface';", + " this._triangleIndexToArea = [];", + " this._tempA = new THREE.Vector3();", + " this._tempB = new THREE.Vector3();", + " this._tempC = new THREE.Vector3();", + " if (!geometry) {", + " return;", + " }", + " this.geometry = geometry;", + " }", + " initialize(p) {", + " const geometry = this._geometry;", + " if (!geometry || geometry.getIndex() === null) {", + " p.position.set(0, 0, 0);", + " p.velocity.set(0, 0, 1).multiplyScalar(p.startSpeed);", + " return;", + " }", + " const triCount = this._triangleIndexToArea.length - 1;", + " let left = 0, right = triCount;", + " const target = Math.random() * this._triangleIndexToArea[triCount];", + " while (left + 1 < right) {", + " const mid = Math.floor((left + right) / 2);", + " if (target < this._triangleIndexToArea[mid]) {", + " right = mid;", + " }", + " else {", + " left = mid;", + " }", + " }", + " let u1 = Math.random();", + " let u2 = Math.random();", + " if (u1 + u2 > 1) {", + " u1 = 1 - u1;", + " u2 = 1 - u2;", + " }", + " const index1 = geometry.getIndex().array[left * 3];", + " const index2 = geometry.getIndex().array[left * 3 + 1];", + " const index3 = geometry.getIndex().array[left * 3 + 2];", + " const positionBuffer = geometry.getAttribute('position');", + " this._tempA.fromBufferAttribute(positionBuffer, index1);", + " this._tempB.fromBufferAttribute(positionBuffer, index2);", + " this._tempC.fromBufferAttribute(positionBuffer, index3);", + " this._tempB.sub(this._tempA);", + " this._tempC.sub(this._tempA);", + " this._tempA.addScaledVector(this._tempB, u1).addScaledVector(this._tempC, u2);", + " p.position.copy(this._tempA);", + " this._tempA.copy(this._tempB).cross(this._tempC).normalize();", + " p.velocity.copy(this._tempA).normalize().multiplyScalar(p.startSpeed);", + " }", + " toJSON() {", + " return {", + " type: 'mesh_surface',", + " mesh: this._geometry ? this._geometry.uuid : '',", + " };", + " }", + " static fromJSON(json, meta) {", + " return new MeshSurfaceEmitter(meta.geometries[json.geometry]);", + " }", + " clone() {", + " return new MeshSurfaceEmitter(this._geometry);", + " }", + " update(system, delta) { }", + "}", + "", + "const EmitterShapes = {", + " circle: {", + " type: 'circle',", + " params: [", + " ['radius', 'number'],", + " ['arc', 'radian'],", + " ['thickness', 'number'],", + " ['mode', 'emitterMode'],", + " ['spread', 'number'],", + " ['speed', 'valueFunc'],", + " ],", + " constructor: CircleEmitter,", + " loadJSON: CircleEmitter.fromJSON,", + " },", + " cone: {", + " type: 'cone',", + " params: [", + " ['radius', 'number'],", + " ['arc', 'radian'],", + " ['thickness', 'number'],", + " ['angle', 'radian'],", + " ['mode', 'emitterMode'],", + " ['spread', 'number'],", + " ['speed', 'valueFunc'],", + " ],", + " constructor: ConeEmitter,", + " loadJSON: ConeEmitter.fromJSON,", + " },", + " donut: {", + " type: 'donut',", + " params: [", + " ['radius', 'number'],", + " ['arc', 'radian'],", + " ['thickness', 'number'],", + " ['donutRadius', 'number'],", + " ['mode', 'emitterMode'],", + " ['spread', 'number'],", + " ['speed', 'valueFunc'],", + " ],", + " constructor: DonutEmitter,", + " loadJSON: DonutEmitter.fromJSON,", + " },", + " point: { type: 'point', params: [], constructor: PointEmitter, loadJSON: PointEmitter.fromJSON },", + " sphere: {", + " type: 'sphere',", + " params: [", + " ['radius', 'number'],", + " ['arc', 'radian'],", + " ['thickness', 'number'],", + " ['angle', 'radian'],", + " ['mode', 'emitterMode'],", + " ['spread', 'number'],", + " ['speed', 'valueFunc'],", + " ],", + " constructor: SphereEmitter,", + " loadJSON: SphereEmitter.fromJSON,", + " },", + " hemisphere: {", + " type: 'hemisphere',", + " params: [", + " ['radius', 'number'],", + " ['arc', 'radian'],", + " ['thickness', 'number'],", + " ['angle', 'radian'],", + " ['mode', 'emitterMode'],", + " ['spread', 'number'],", + " ['speed', 'valueFunc'],", + " ],", + " constructor: HemisphereEmitter,", + " loadJSON: HemisphereEmitter.fromJSON,", + " },", + " grid: {", + " type: 'grid',", + " params: [", + " ['width', 'number'],", + " ['height', 'number'],", + " ['rows', 'number'],", + " ['column', 'number'],", + " ],", + " constructor: GridEmitter,", + " loadJSON: GridEmitter.fromJSON,", + " },", + " mesh_surface: {", + " type: 'mesh_surface',", + " params: [['geometry', 'geometry']],", + " constructor: MeshSurfaceEmitter,", + " loadJSON: MeshSurfaceEmitter.fromJSON,", + " },", + "};", + "function EmitterFromJSON(json, meta) {", + " return EmitterShapes[json.type].loadJSON(json, meta);", + "}", + "", + "let RenderMode = void 0;", + "(function (RenderMode) {", + " RenderMode[RenderMode[\"BillBoard\"] = 0] = \"BillBoard\";", + " RenderMode[RenderMode[\"StretchedBillBoard\"] = 1] = \"StretchedBillBoard\";", + " RenderMode[RenderMode[\"Mesh\"] = 2] = \"Mesh\";", + " RenderMode[RenderMode[\"Trail\"] = 3] = \"Trail\";", + " RenderMode[RenderMode[\"HorizontalBillBoard\"] = 4] = \"HorizontalBillBoard\";", + " RenderMode[RenderMode[\"VerticalBillBoard\"] = 5] = \"VerticalBillBoard\";", + "})(RenderMode || (RenderMode = {}));", + "class VFXBatch extends THREE.Mesh {", + " constructor(settings) {", + " super();", + " this.type = 'VFXBatch';", + " this.maxParticles = 1000;", + " this.systems = new Set();", + " const layers = new THREE.Layers();", + " layers.mask = settings.layers.mask;", + " const newMat = settings.material.clone();", + " newMat.defines = {};", + " Object.assign(newMat.defines, settings.material.defines);", + " this.settings = {", + " instancingGeometry: settings.instancingGeometry,", + " renderMode: settings.renderMode,", + " renderOrder: settings.renderOrder,", + " material: newMat,", + " uTileCount: settings.uTileCount,", + " vTileCount: settings.vTileCount,", + " layers: layers,", + " };", + " this.frustumCulled = false;", + " this.renderOrder = this.settings.renderOrder;", + " }", + " addSystem(system) {", + " this.systems.add(system);", + " }", + " removeSystem(system) {", + " this.systems.delete(system);", + " }", + "}", + "", + "const UP = new THREE.Vector3(0, 0, 1);", + "const tempQ$1 = new THREE.Quaternion();", + "const tempV$1 = new THREE.Vector3();", + "const tempV2$1 = new THREE.Vector3();", + "new THREE.Vector3();", + "const PREWARM_FPS$1 = 60;", + "const DEFAULT_GEOMETRY$1 = new THREE.PlaneGeometry(1, 1, 1, 1);", + "class ParticleSystem {", + " set time(time) {", + " this.emissionState.time = time;", + " }", + " get time() {", + " return this.emissionState.time;", + " }", + " get layers() {", + " return this.rendererSettings.layers;", + " }", + " get texture() {", + " return this.rendererSettings.material.map;", + " }", + " set texture(texture) {", + " this.rendererSettings.material.map = texture;", + " this.neededToUpdateRender = true;", + " }", + " get material() {", + " return this.rendererSettings.material;", + " }", + " set material(material) {", + " this.rendererSettings.material = material;", + " this.neededToUpdateRender = true;", + " }", + " get uTileCount() {", + " return this.rendererSettings.uTileCount;", + " }", + " set uTileCount(u) {", + " this.rendererSettings.uTileCount = u;", + " this.neededToUpdateRender = true;", + " }", + " get vTileCount() {", + " return this.rendererSettings.vTileCount;", + " }", + " set vTileCount(v) {", + " this.rendererSettings.vTileCount = v;", + " this.neededToUpdateRender = true;", + " }", + " get instancingGeometry() {", + " return this.rendererSettings.instancingGeometry;", + " }", + " set instancingGeometry(geometry) {", + " this.restart();", + " this.particles.length = 0;", + " this.rendererSettings.instancingGeometry = geometry;", + " this.neededToUpdateRender = true;", + " }", + " get renderMode() {", + " return this.rendererSettings.renderMode;", + " }", + " set renderMode(renderMode) {", + " if ((this.rendererSettings.renderMode != RenderMode.Trail && renderMode === RenderMode.Trail) ||", + " (this.rendererSettings.renderMode == RenderMode.Trail && renderMode !== RenderMode.Trail)) {", + " this.restart();", + " this.particles.length = 0;", + " }", + " if (this.rendererSettings.renderMode !== renderMode) {", + " switch (renderMode) {", + " case RenderMode.Trail:", + " this.rendererEmitterSettings = {", + " startLength: new ConstantValue(30),", + " followLocalOrigin: false,", + " };", + " break;", + " case RenderMode.Mesh:", + " this.rendererEmitterSettings = {", + " geometry: new THREE.PlaneGeometry(1, 1),", + " };", + " this.startRotation = new AxisAngleGenerator(new THREE.Vector3(0, 1, 0), new ConstantValue(0));", + " break;", + " case RenderMode.StretchedBillBoard:", + " this.rendererEmitterSettings = { speedFactor: 0, lengthFactor: 2 };", + " if (this.rendererSettings.renderMode === RenderMode.Mesh) {", + " this.startRotation = new ConstantValue(0);", + " }", + " break;", + " case RenderMode.BillBoard:", + " case RenderMode.VerticalBillBoard:", + " case RenderMode.HorizontalBillBoard:", + " this.rendererEmitterSettings = {};", + " if (this.rendererSettings.renderMode === RenderMode.Mesh) {", + " this.startRotation = new ConstantValue(0);", + " }", + " break;", + " }", + " }", + " this.rendererSettings.renderMode = renderMode;", + " this.neededToUpdateRender = true;", + " }", + " get renderOrder() {", + " return this.rendererSettings.renderOrder;", + " }", + " set renderOrder(renderOrder) {", + " this.rendererSettings.renderOrder = renderOrder;", + " this.neededToUpdateRender = true;", + " }", + " get blending() {", + " return this.rendererSettings.material.blending;", + " }", + " set blending(blending) {", + " this.rendererSettings.material.blending = blending;", + " this.neededToUpdateRender = true;", + " }", + " constructor(parameters) {", + " var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;", + " this.temp = new THREE.Vector3();", + " this.travelDistance = 0;", + " this.normalMatrix = new THREE.Matrix3();", + " this.firstTimeUpdate = true;", + " this.autoDestroy = parameters.autoDestroy === undefined ? false : parameters.autoDestroy;", + " this.duration = (_a = parameters.duration) !== null && _a !== void 0 ? _a : 1;", + " this.looping = parameters.looping === undefined ? true : parameters.looping;", + " this.prewarm = parameters.prewarm === undefined ? false : parameters.prewarm;", + " this.startLife = (_b = parameters.startLife) !== null && _b !== void 0 ? _b : new ConstantValue(5);", + " this.startSpeed = (_c = parameters.startSpeed) !== null && _c !== void 0 ? _c : new ConstantValue(0);", + " this.startRotation = (_d = parameters.startRotation) !== null && _d !== void 0 ? _d : new ConstantValue(0);", + " this.startSize = (_e = parameters.startSize) !== null && _e !== void 0 ? _e : new ConstantValue(1);", + " this.startColor = (_f = parameters.startColor) !== null && _f !== void 0 ? _f : new ConstantColor(new THREE.Vector4(1, 1, 1, 1));", + " this.emissionOverTime = (_g = parameters.emissionOverTime) !== null && _g !== void 0 ? _g : new ConstantValue(10);", + " this.emissionOverDistance = (_h = parameters.emissionOverDistance) !== null && _h !== void 0 ? _h : new ConstantValue(0);", + " this.emissionBursts = (_j = parameters.emissionBursts) !== null && _j !== void 0 ? _j : [];", + " this.onlyUsedByOther = (_k = parameters.onlyUsedByOther) !== null && _k !== void 0 ? _k : false;", + " this.emitterShape = (_l = parameters.shape) !== null && _l !== void 0 ? _l : new SphereEmitter();", + " this.behaviors = (_m = parameters.behaviors) !== null && _m !== void 0 ? _m : new Array();", + " this.worldSpace = (_o = parameters.worldSpace) !== null && _o !== void 0 ? _o : false;", + " this.rendererEmitterSettings = (_p = parameters.rendererEmitterSettings) !== null && _p !== void 0 ? _p : {};", + " if (parameters.renderMode === RenderMode.StretchedBillBoard) {", + " const stretchedBillboardSettings = this.rendererEmitterSettings;", + " if (parameters.speedFactor !== undefined) {", + " stretchedBillboardSettings.speedFactor = parameters.speedFactor;", + " }", + " stretchedBillboardSettings.speedFactor = (_q = stretchedBillboardSettings.speedFactor) !== null && _q !== void 0 ? _q : 0;", + " stretchedBillboardSettings.lengthFactor = (_r = stretchedBillboardSettings.lengthFactor) !== null && _r !== void 0 ? _r : 0;", + " }", + " this.rendererSettings = {", + " instancingGeometry: (_s = parameters.instancingGeometry) !== null && _s !== void 0 ? _s : DEFAULT_GEOMETRY$1,", + " renderMode: (_t = parameters.renderMode) !== null && _t !== void 0 ? _t : RenderMode.BillBoard,", + " renderOrder: (_u = parameters.renderOrder) !== null && _u !== void 0 ? _u : 0,", + " material: parameters.material,", + " uTileCount: (_v = parameters.uTileCount) !== null && _v !== void 0 ? _v : 1,", + " vTileCount: (_w = parameters.vTileCount) !== null && _w !== void 0 ? _w : 1,", + " layers: (_x = parameters.layers) !== null && _x !== void 0 ? _x : new THREE.Layers(),", + " };", + " this.neededToUpdateRender = true;", + " this.particles = new Array();", + " this.startTileIndex = parameters.startTileIndex || new ConstantValue(0);", + " this.emitter = new ParticleEmitter(this);", + " this.paused = false;", + " this.particleNum = 0;", + " this.emissionState = {", + " burstIndex: 0,", + " burstWaveIndex: 0,", + " time: 0,", + " waitEmiting: 0,", + " travelDistance: 0,", + " };", + " this.emitEnded = false;", + " this.markForDestroy = false;", + " this.prewarmed = false;", + " }", + " pause() {", + " this.paused = true;", + " }", + " play() {", + " this.paused = false;", + " }", + " spawn(count, emissionState, matrix) {", + " tempQ$1.setFromRotationMatrix(matrix);", + " const translation = tempV$1;", + " const quaternion = tempQ$1;", + " const scale = tempV2$1;", + " matrix.decompose(translation, quaternion, scale);", + " for (let i = 0; i < count; i++) {", + " this.particleNum++;", + " while (this.particles.length < this.particleNum) {", + " if (this.rendererSettings.renderMode === RenderMode.Trail) {", + " this.particles.push(new TrailParticle());", + " }", + " else {", + " this.particles.push(new SpriteParticle());", + " }", + " }", + " const particle = this.particles[this.particleNum - 1];", + " particle.speedModifier = 1;", + " this.startColor.genColor(particle.startColor, this.emissionState.time, {});", + " particle.color.copy(particle.startColor);", + " particle.startSpeed = this.startSpeed.genValue(emissionState.time / this.duration);", + " particle.life = this.startLife.genValue(emissionState.time / this.duration);", + " particle.age = 0;", + " particle.startSize = this.startSize.genValue(emissionState.time / this.duration);", + " particle.uvTile = Math.floor(this.startTileIndex.genValue() + 0.001);", + " particle.size = particle.startSize;", + " if (this.rendererSettings.renderMode === RenderMode.Mesh ||", + " this.rendererSettings.renderMode === RenderMode.BillBoard ||", + " this.rendererSettings.renderMode === RenderMode.VerticalBillBoard ||", + " this.rendererSettings.renderMode === RenderMode.HorizontalBillBoard ||", + " this.rendererSettings.renderMode === RenderMode.StretchedBillBoard) {", + " const sprite = particle;", + " if (this.rendererSettings.renderMode === RenderMode.Mesh) {", + " if (!(sprite.rotation instanceof THREE.Quaternion)) {", + " sprite.rotation = new THREE.Quaternion();", + " }", + " if (this.startRotation.type === 'rotation') {", + " this.startRotation.genValue(sprite.rotation, emissionState.time / this.duration);", + " }", + " else {", + " sprite.rotation.setFromAxisAngle(UP, this.startRotation.genValue((emissionState.time / this.duration)));", + " }", + " }", + " else {", + " if (this.startRotation.type === 'rotation') {", + " sprite.rotation = 0;", + " }", + " else {", + " sprite.rotation = this.startRotation.genValue(emissionState.time / this.duration);", + " }", + " }", + " }", + " else if (this.rendererSettings.renderMode === RenderMode.Trail) {", + " const trail = particle;", + " trail.length = this.rendererEmitterSettings.startLength.genValue(emissionState.time / this.duration);", + " }", + " this.emitterShape.initialize(particle);", + " if (this.rendererSettings.renderMode === RenderMode.Trail &&", + " this.rendererEmitterSettings.followLocalOrigin) {", + " const trail = particle;", + " trail.localPosition = new THREE.Vector3().copy(trail.position);", + " }", + " if (this.worldSpace) {", + " particle.position.applyMatrix4(matrix);", + " particle.startSize =", + " (particle.startSize * (Math.abs(scale.x) + Math.abs(scale.y) + Math.abs(scale.z))) / 3;", + " particle.size = particle.startSize;", + " particle.velocity.multiply(scale).applyMatrix3(this.normalMatrix);", + " if (particle.rotation && particle.rotation instanceof THREE.Quaternion) {", + " particle.rotation.multiplyQuaternions(tempQ$1, particle.rotation);", + " }", + " }", + " else {", + " if (this.onlyUsedByOther) {", + " particle.parentMatrix = matrix;", + " }", + " }", + " for (let j = 0; j < this.behaviors.length; j++) {", + " this.behaviors[j].initialize(particle);", + " }", + " }", + " }", + " endEmit() {", + " this.emitEnded = true;", + " if (this.autoDestroy) {", + " this.markForDestroy = true;", + " }", + " }", + " dispose() {", + " if (this._renderer)", + " this._renderer.deleteSystem(this);", + " this.emitter.dispose();", + " if (this.emitter.parent)", + " this.emitter.parent.remove(this.emitter);", + " }", + " restart() {", + " this.paused = false;", + " this.particleNum = 0;", + " this.emissionState.burstIndex = 0;", + " this.emissionState.burstWaveIndex = 0;", + " this.emissionState.time = 0;", + " this.emissionState.waitEmiting = 0;", + " this.behaviors.forEach((behavior) => {", + " behavior.reset();", + " });", + " this.emitEnded = false;", + " this.markForDestroy = false;", + " this.prewarmed = false;", + " }", + " update(delta) {", + " if (this.paused)", + " return;", + " let currentParent = this.emitter;", + " while (currentParent.parent) {", + " currentParent = currentParent.parent;", + " }", + " if (currentParent.type !== 'Scene') {", + " this.dispose();", + " return;", + " }", + " if (this.firstTimeUpdate) {", + " this.firstTimeUpdate = false;", + " this.emitter.updateWorldMatrix(true, false);", + " }", + " if (this.emitEnded && this.particleNum === 0) {", + " if (this.markForDestroy && this.emitter.parent)", + " this.dispose();", + " return;", + " }", + " if (this.looping && this.prewarm && !this.prewarmed) {", + " this.prewarmed = true;", + " for (let i = 0; i < this.duration * PREWARM_FPS$1; i++) {", + " this.update(1.0 / PREWARM_FPS$1);", + " }", + " }", + " if (delta > 0.1) {", + " delta = 0.1;", + " }", + " if (this.neededToUpdateRender) {", + " if (this._renderer)", + " this._renderer.updateSystem(this);", + " this.neededToUpdateRender = false;", + " }", + " if (!this.onlyUsedByOther) {", + " this.emit(delta, this.emissionState, this.emitter.matrixWorld);", + " }", + " this.emitterShape.update(this, delta);", + " for (let j = 0; j < this.behaviors.length; j++) {", + " for (let i = 0; i < this.particleNum; i++) {", + " if (!this.particles[i].died) {", + " this.behaviors[j].update(this.particles[i], delta);", + " }", + " }", + " this.behaviors[j].frameUpdate(delta);", + " }", + " for (let i = 0; i < this.particleNum; i++) {", + " if (this.rendererEmitterSettings.followLocalOrigin &&", + " this.particles[i].localPosition) {", + " this.particles[i].position.copy(this.particles[i].localPosition);", + " if (this.particles[i].parentMatrix) {", + " this.particles[i].position.applyMatrix4(this.particles[i].parentMatrix);", + " }", + " else {", + " this.particles[i].position.applyMatrix4(this.emitter.matrixWorld);", + " }", + " }", + " else {", + " this.particles[i].position.addScaledVector(this.particles[i].velocity, delta * this.particles[i].speedModifier);", + " }", + " this.particles[i].age += delta;", + " }", + " if (this.rendererSettings.renderMode === RenderMode.Trail) {", + " for (let i = 0; i < this.particleNum; i++) {", + " const particle = this.particles[i];", + " particle.update();", + " }", + " }", + " for (let i = 0; i < this.particleNum; i++) {", + " const particle = this.particles[i];", + " if (particle.died && (!(particle instanceof TrailParticle) || particle.previous.length === 0)) {", + " this.particles[i] = this.particles[this.particleNum - 1];", + " this.particles[this.particleNum - 1] = particle;", + " this.particleNum--;", + " i--;", + " }", + " }", + " }", + " emit(delta, emissionState, emitterMatrix) {", + " if (emissionState.time > this.duration) {", + " if (this.looping) {", + " emissionState.time -= this.duration;", + " emissionState.burstIndex = 0;", + " this.behaviors.forEach((behavior) => {", + " behavior.reset();", + " });", + " }", + " else {", + " if (!this.emitEnded && !this.onlyUsedByOther) {", + " this.endEmit();", + " }", + " }", + " }", + " this.normalMatrix.getNormalMatrix(emitterMatrix);", + " const totalSpawn = Math.ceil(emissionState.waitEmiting);", + " this.spawn(totalSpawn, emissionState, emitterMatrix);", + " emissionState.waitEmiting -= totalSpawn;", + " while (emissionState.burstIndex < this.emissionBursts.length &&", + " this.emissionBursts[emissionState.burstIndex].time <= emissionState.time) {", + " if (Math.random() < this.emissionBursts[emissionState.burstIndex].probability) {", + " const count = this.emissionBursts[emissionState.burstIndex].count.genValue(this.time);", + " this.spawn(count, emissionState, emitterMatrix);", + " }", + " emissionState.burstIndex++;", + " }", + " if (!this.emitEnded) {", + " emissionState.waitEmiting += delta * this.emissionOverTime.genValue(emissionState.time / this.duration);", + " if (emissionState.previousWorldPos != undefined) {", + " this.temp.set(emitterMatrix.elements[12], emitterMatrix.elements[13], emitterMatrix.elements[14]);", + " emissionState.travelDistance += emissionState.previousWorldPos.distanceTo(this.temp);", + " const emitPerMeter = this.emissionOverDistance.genValue(emissionState.time / this.duration);", + " if (emissionState.travelDistance * emitPerMeter > 0) {", + " const count = Math.floor(emissionState.travelDistance * emitPerMeter);", + " emissionState.travelDistance -= count / emitPerMeter;", + " emissionState.waitEmiting += count;", + " }", + " }", + " }", + " if (emissionState.previousWorldPos === undefined)", + " emissionState.previousWorldPos = new THREE.Vector3();", + " emissionState.previousWorldPos.set(emitterMatrix.elements[12], emitterMatrix.elements[13], emitterMatrix.elements[14]);", + " emissionState.time += delta;", + " }", + " toJSON(meta, options = {}) {", + " const isRootObject = meta === undefined || typeof meta === 'string';", + " if (isRootObject) {", + " meta = {", + " geometries: {},", + " materials: {},", + " textures: {},", + " images: {},", + " shapes: {},", + " skeletons: {},", + " animations: {},", + " nodes: {},", + " };", + " }", + " meta.materials[this.rendererSettings.material.uuid] = this.rendererSettings.material.toJSON(meta);", + " if (options.useUrlForImage) {", + " if (this.texture.source !== undefined) {", + " const image = this.texture.source;", + " meta.images[image.uuid] = {", + " uuid: image.uuid,", + " url: this.texture.image.url,", + " };", + " }", + " }", + " let rendererSettingsJSON;", + " if (this.renderMode === RenderMode.Trail) {", + " rendererSettingsJSON = {", + " startLength: this.rendererEmitterSettings.startLength.toJSON(),", + " followLocalOrigin: this.rendererEmitterSettings.followLocalOrigin,", + " };", + " }", + " else if (this.renderMode === RenderMode.Mesh) {", + " rendererSettingsJSON = {};", + " }", + " else if (this.renderMode === RenderMode.StretchedBillBoard) {", + " rendererSettingsJSON = {", + " speedFactor: this.rendererEmitterSettings.speedFactor,", + " lengthFactor: this.rendererEmitterSettings.lengthFactor,", + " };", + " }", + " else {", + " rendererSettingsJSON = {};", + " }", + " const geometry = this.rendererSettings.instancingGeometry;", + " if (meta.geometries && !meta.geometries[geometry.uuid]) {", + " meta.geometries[geometry.uuid] = geometry.toJSON();", + " }", + " return {", + " version: '2.0',", + " autoDestroy: this.autoDestroy,", + " looping: this.looping,", + " prewarm: this.prewarm,", + " duration: this.duration,", + " shape: this.emitterShape.toJSON(),", + " startLife: this.startLife.toJSON(),", + " startSpeed: this.startSpeed.toJSON(),", + " startRotation: this.startRotation.toJSON(),", + " startSize: this.startSize.toJSON(),", + " startColor: this.startColor.toJSON(),", + " emissionOverTime: this.emissionOverTime.toJSON(),", + " emissionOverDistance: this.emissionOverDistance.toJSON(),", + " emissionBursts: this.emissionBursts.map((burst) => ({", + " time: burst.time,", + " count: burst.count.toJSON(),", + " probability: burst.probability,", + " interval: burst.interval,", + " cycle: burst.cycle,", + " })),", + " onlyUsedByOther: this.onlyUsedByOther,", + " instancingGeometry: this.rendererSettings.instancingGeometry.uuid,", + " renderOrder: this.renderOrder,", + " renderMode: this.renderMode,", + " rendererEmitterSettings: rendererSettingsJSON,", + " material: this.rendererSettings.material.uuid,", + " layers: this.layers.mask,", + " startTileIndex: this.startTileIndex.toJSON(),", + " uTileCount: this.uTileCount,", + " vTileCount: this.vTileCount,", + " behaviors: this.behaviors.map((behavior) => behavior.toJSON()),", + " worldSpace: this.worldSpace,", + " };", + " }", + " static fromJSON(json, meta, dependencies) {", + " var _a, _b;", + " const shape = EmitterFromJSON(json.shape, meta);", + " let rendererEmitterSettings;", + " if (json.renderMode === RenderMode.Trail) {", + " let trailSettings = json.rendererEmitterSettings;", + " rendererEmitterSettings = {", + " startLength: trailSettings.startLength != undefined", + " ? ValueGeneratorFromJSON(trailSettings.startLength)", + " : new ConstantValue(30),", + " followLocalOrigin: trailSettings.followLocalOrigin,", + " };", + " }", + " else if (json.renderMode === RenderMode.Mesh) {", + " rendererEmitterSettings = {};", + " }", + " else if (json.renderMode === RenderMode.StretchedBillBoard) {", + " rendererEmitterSettings = json.rendererEmitterSettings;", + " if (json.speedFactor != undefined) {", + " rendererEmitterSettings.speedFactor = json.speedFactor;", + " }", + " }", + " else {", + " rendererEmitterSettings = {};", + " }", + " const layers = new THREE.Layers();", + " if (json.layers) {", + " layers.mask = json.layers;", + " }", + " const ps = new ParticleSystem({", + " autoDestroy: json.autoDestroy,", + " looping: json.looping,", + " prewarm: json.prewarm,", + " duration: json.duration,", + " shape: shape,", + " startLife: ValueGeneratorFromJSON(json.startLife),", + " startSpeed: ValueGeneratorFromJSON(json.startSpeed),", + " startRotation: GeneratorFromJSON(json.startRotation),", + " startSize: ValueGeneratorFromJSON(json.startSize),", + " startColor: ColorGeneratorFromJSON(json.startColor),", + " emissionOverTime: ValueGeneratorFromJSON(json.emissionOverTime),", + " emissionOverDistance: ValueGeneratorFromJSON(json.emissionOverDistance),", + " emissionBursts: (_a = json.emissionBursts) === null || _a === void 0 ? void 0 : _a.map((burst) => ({", + " time: burst.time,", + " count: typeof burst.count === 'number'", + " ? new ConstantValue(burst.count)", + " : ValueGeneratorFromJSON(burst.count),", + " probability: burst.probability,", + " interval: burst.interval,", + " cycle: burst.cycle,", + " })),", + " onlyUsedByOther: json.onlyUsedByOther,", + " instancingGeometry: meta.geometries[json.instancingGeometry],", + " renderMode: json.renderMode,", + " rendererEmitterSettings: rendererEmitterSettings,", + " renderOrder: json.renderOrder,", + " layers: layers,", + " material: json.material", + " ? meta.materials[json.material]", + " : json.texture", + " ? new THREE.MeshBasicMaterial({", + " map: meta.textures[json.texture],", + " transparent: (_b = json.transparent) !== null && _b !== void 0 ? _b : true,", + " blending: json.blending,", + " side: THREE.DoubleSide,", + " })", + " : new THREE.MeshBasicMaterial({", + " color: 0xffffff,", + " transparent: true,", + " blending: THREE.AdditiveBlending,", + " side: THREE.DoubleSide,", + " }),", + " startTileIndex: typeof json.startTileIndex === 'number'", + " ? new ConstantValue(json.startTileIndex)", + " : ValueGeneratorFromJSON(json.startTileIndex),", + " uTileCount: json.uTileCount,", + " vTileCount: json.vTileCount,", + " behaviors: [],", + " worldSpace: json.worldSpace,", + " });", + " ps.behaviors = json.behaviors.map((behaviorJson) => {", + " const behavior = BehaviorFromJSON(behaviorJson, ps);", + " if (behavior.type === 'EmitSubParticleSystem') {", + " dependencies[behaviorJson.subParticleSystem] = behavior;", + " }", + " return behavior;", + " });", + " return ps;", + " }", + " addBehavior(behavior) {", + " this.behaviors.push(behavior);", + " }", + " getRendererSettings() {", + " return this.rendererSettings;", + " }", + " clone() {", + " const newEmissionBursts = [];", + " for (const emissionBurst of this.emissionBursts) {", + " const newEmissionBurst = {};", + " Object.assign(newEmissionBurst, emissionBurst);", + " newEmissionBursts.push(newEmissionBurst);", + " }", + " const newBehaviors = [];", + " for (const behavior of this.behaviors) {", + " newBehaviors.push(behavior.clone());", + " }", + " let rendererEmitterSettings;", + " if (this.renderMode === RenderMode.Trail) {", + " rendererEmitterSettings = {", + " startLength: this.rendererEmitterSettings.startLength.clone(),", + " followLocalOrigin: this.rendererEmitterSettings.followLocalOrigin,", + " };", + " }", + " else {", + " rendererEmitterSettings = {};", + " }", + " const layers = new THREE.Layers();", + " layers.mask = this.layers.mask;", + " return new ParticleSystem({", + " autoDestroy: this.autoDestroy,", + " looping: this.looping,", + " duration: this.duration,", + " shape: this.emitterShape.clone(),", + " startLife: this.startLife.clone(),", + " startSpeed: this.startSpeed.clone(),", + " startRotation: this.startRotation.clone(),", + " startSize: this.startSize.clone(),", + " startColor: this.startColor.clone(),", + " emissionOverTime: this.emissionOverTime.clone(),", + " emissionOverDistance: this.emissionOverDistance.clone(),", + " emissionBursts: newEmissionBursts,", + " onlyUsedByOther: this.onlyUsedByOther,", + " instancingGeometry: this.rendererSettings.instancingGeometry,", + " renderMode: this.renderMode,", + " renderOrder: this.renderOrder,", + " rendererEmitterSettings: rendererEmitterSettings,", + " material: this.rendererSettings.material,", + " startTileIndex: this.startTileIndex,", + " uTileCount: this.uTileCount,", + " vTileCount: this.vTileCount,", + " behaviors: newBehaviors,", + " worldSpace: this.worldSpace,", + " layers: layers,", + " });", + " }", + "}", + "", + "var particle_frag = `", + "", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "void main() {", + "", + " #include ", + " ", + " vec3 outgoingLight = vec3( 0.0 );", + " vec4 diffuseColor = vColor;", + " ", + " #include ", + " ", + " #ifdef USE_MAP", + " diffuseColor *= texture2D( map, vMapUv);", + " #endif", + " ", + " #include ", + "", + " outgoingLight = diffuseColor.rgb;", + " ", + " #ifdef USE_COLOR_AS_ALPHA", + " gl_FragColor = vec4( outgoingLight, diffuseColor.r );", + " #else", + " gl_FragColor = vec4( outgoingLight, diffuseColor.a );", + " #endif", + " ", + " ", + " #include ", + "", + "}", + "`;", + "", + "var particle_physics_frag = `", + "#define STANDARD", + "#ifdef PHYSICAL", + "#define IOR", + "#define SPECULAR", + "#endif", + "uniform vec3 diffuse;", + "uniform vec3 emissive;", + "uniform float roughness;", + "uniform float metalness;", + "uniform float opacity;", + "#ifdef IOR", + "uniform float ior;", + "#endif", + "#ifdef SPECULAR", + "uniform float specularIntensity;", + "uniform vec3 specularColor;", + "#ifdef USE_SPECULARINTENSITYMAP", + "uniform sampler2D specularIntensityMap;", + "#endif", + "#ifdef USE_SPECULARCOLORMAP", + "uniform sampler2D specularColorMap;", + "#endif", + "#endif", + "#ifdef USE_CLEARCOAT", + "uniform float clearcoat;", + "uniform float clearcoatRoughness;", + "#endif", + "#ifdef USE_IRIDESCENCE", + "uniform float iridescence;", + "uniform float iridescenceIOR;", + "uniform float iridescenceThicknessMinimum;", + "uniform float iridescenceThicknessMaximum;", + "#endif", + "#ifdef USE_SHEEN", + "uniform vec3 sheenColor;", + "uniform float sheenRoughness;", + "#ifdef USE_SHEENCOLORMAP", + "uniform sampler2D sheenColorMap;", + "#endif", + "#ifdef USE_SHEENROUGHNESSMAP", + "uniform sampler2D sheenRoughnessMap;", + "#endif", + "#endif", + "", + "varying vec3 vViewPosition;", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "void main() {", + " #include ", + " vec4 diffuseColor = vec4( diffuse, opacity );", + " ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );", + " vec3 totalEmissiveRadiance = emissive;", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " // accumulation", + " #include ", + " #include ", + " #include ", + " #include ", + " // modulation", + " #include ", + " vec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;", + " vec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;", + " #include ", + " vec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;", + " #ifdef USE_SHEEN", + " // Sheen energy compensation approximation calculation can be found at the end of", + " // https://drive.google.com/file/d/1T0D1VSyR4AllqIJTQAraEIzjlb5h4FKH/view?usp=sharing", + " float sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );", + " outgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;", + " #endif", + " #ifdef USE_CLEARCOAT", + " float dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );", + " vec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );", + " outgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;", + " #endif", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + " #include ", + "}`;", + "", + "var uv_vertex_tile = `", + "", + " #ifdef UV_TILE", + " float col = mod(uvTile, tileCount.x);", + " float row = (tileCount.y - floor(uvTile / tileCount.x) - 1.0);", + " ", + " mat3 tileTransform = mat3(", + " 1.0 / tileCount.x, 0.0, 0.0,", + " 0.0, 1.0 / tileCount.y, 0.0, ", + " col / tileCount.x, row / tileCount.y, 1.0);", + " #else", + " mat3 tileTransform = mat3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);", + " #endif", + "", + "#if defined( USE_UV ) || defined( USE_ANISOTROPY )", + "", + "vUv = (tileTransform *vec3( uv, 1 )).xy;", + "", + "#endif", + "#ifdef USE_MAP", + "", + "vMapUv = ( tileTransform * (mapTransform * vec3( MAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_ALPHAMAP", + "", + "vAlphaMapUv = ( tileTransform * (alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_LIGHTMAP", + "", + "vLightMapUv = ( tileTransform * (lightMapTransform * vec3( LIGHTMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_AOMAP", + "", + "vAoMapUv = ( tileTransform * (aoMapTransform * vec3( AOMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_BUMPMAP", + "", + "vBumpMapUv = ( tileTransform * (bumpMapTransform * vec3( BUMPMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_NORMALMAP", + "", + "vNormalMapUv = ( tileTransform * (normalMapTransform * vec3( NORMALMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_DISPLACEMENTMAP", + "", + "vDisplacementMapUv = ( tileTransform * (displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_EMISSIVEMAP", + "", + "vEmissiveMapUv = ( tileTransform * (emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_METALNESSMAP", + "", + "vMetalnessMapUv = ( tileTransform * (metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_ROUGHNESSMAP", + "", + "vRoughnessMapUv = ( tileTransform * (roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_ANISOTROPYMAP", + "", + "vAnisotropyMapUv = ( tileTransform * (anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_CLEARCOATMAP", + "", + "vClearcoatMapUv = ( tileTransform * (clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_CLEARCOAT_NORMALMAP", + "", + "vClearcoatNormalMapUv = ( tileTransform * (clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_CLEARCOAT_ROUGHNESSMAP", + "", + "vClearcoatRoughnessMapUv = ( tileTransform * (clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_IRIDESCENCEMAP", + "", + "vIridescenceMapUv = ( tileTransform * (iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_IRIDESCENCE_THICKNESSMAP", + "", + "vIridescenceThicknessMapUv = ( tileTransform * (iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_SHEEN_COLORMAP", + "", + "vSheenColorMapUv = ( tileTransform * (sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_SHEEN_ROUGHNESSMAP", + "", + "vSheenRoughnessMapUv = ( tileTransform * (sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_SPECULARMAP", + "", + "vSpecularMapUv = ( tileTransform * (specularMapTransform * vec3( SPECULARMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_SPECULAR_COLORMAP", + "", + "vSpecularColorMapUv = ( tileTransform * (specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_SPECULAR_INTENSITYMAP", + "", + "vSpecularIntensityMapUv = ( tileTransform * (specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_TRANSMISSIONMAP", + "", + "vTransmissionMapUv = ( tileTransform * transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) )).xy;", + "", + "#endif", + "#ifdef USE_THICKNESSMAP", + "", + "vThicknessMapUv = ( tileTransform * thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) )).xy;", + "", + "#endif", + "`;", + "", + "var particle_vert = `", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "attribute vec3 offset;", + "attribute float rotation;", + "attribute float size;", + "attribute float uvTile;", + "", + "#ifdef UV_TILE", + "uniform vec2 tileCount;", + "#endif", + "", + "void main() {", + "", + " ${uv_vertex_tile}", + "\t", + " vec2 alignedPosition = ( position.xy ) * size;", + " ", + " vec2 rotatedPosition;", + " rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;", + " rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;", + "#ifdef HORIZONTAL", + " vec4 mvPosition = modelMatrix * vec4( offset, 1.0 );", + " mvPosition.x += rotatedPosition.x;", + " mvPosition.z -= rotatedPosition.y;", + " mvPosition = viewMatrix * mvPosition;", + "#elif defined(VERTICAL)", + " vec4 mvPosition = modelMatrix * vec4( offset, 1.0 );", + " mvPosition.y += rotatedPosition.y;", + " mvPosition = viewMatrix * mvPosition;", + " mvPosition.x += rotatedPosition.x;", + "#else", + " vec4 mvPosition = modelViewMatrix * vec4( offset, 1.0 );", + " mvPosition.xy += rotatedPosition;", + "#endif", + "", + "\tvColor = color;", + "", + "\tgl_Position = projectionMatrix * mvPosition;", + "", + "\t#include ", + "\t#include ", + "", + "}", + "`;", + "", + "var local_particle_vert = `", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "attribute vec3 offset;", + "attribute vec4 rotation;", + "attribute float size;", + "// attribute vec4 color;", + "attribute float uvTile;", + "", + "#ifdef UV_TILE", + "uniform vec2 tileCount;", + "#endif", + "", + "void main() {", + "", + " ${uv_vertex_tile}", + " ", + " float x2 = rotation.x + rotation.x, y2 = rotation.y + rotation.y, z2 = rotation.z + rotation.z;", + " float xx = rotation.x * x2, xy = rotation.x * y2, xz = rotation.x * z2;", + " float yy = rotation.y * y2, yz = rotation.y * z2, zz = rotation.z * z2;", + " float wx = rotation.w * x2, wy = rotation.w * y2, wz = rotation.w * z2;", + " float sx = size, sy = size, sz = size;", + " ", + " mat4 matrix = mat4(( 1.0 - ( yy + zz ) ) * sx, ( xy + wz ) * sx, ( xz - wy ) * sx, 0.0, // 1. column", + " ( xy - wz ) * sy, ( 1.0 - ( xx + zz ) ) * sy, ( yz + wx ) * sy, 0.0, // 2. column", + " ( xz + wy ) * sz, ( yz - wx ) * sz, ( 1.0 - ( xx + yy ) ) * sz, 0.0, // 3. column", + " offset.x, offset.y, offset.z, 1.0);", + " ", + " vec4 mvPosition = modelViewMatrix * (matrix * vec4( position, 1.0 ));", + "", + "\tvColor = color;", + "", + "\tgl_Position = projectionMatrix * mvPosition;", + "", + "\t#include ", + "\t#include ", + "", + "}", + "`;", + "", + "var local_particle_physics_vert = `", + "#define STANDARD", + "varying vec3 vViewPosition;", + "#ifdef USE_TRANSMISSION", + "\tvarying vec3 vWorldPosition;", + "#endif", + "#include ", + "#include ", + "", + "attribute vec3 offset;", + "attribute vec4 rotation;", + "attribute float size;", + "attribute float uvTile;", + "", + "#ifdef UV_TILE", + "uniform vec2 tileCount;", + "#endif", + "", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "void main() {", + " ${uv_vertex_tile}", + "", + " float x2 = rotation.x + rotation.x, y2 = rotation.y + rotation.y, z2 = rotation.z + rotation.z;", + " float xx = rotation.x * x2, xy = rotation.x * y2, xz = rotation.x * z2;", + " float yy = rotation.y * y2, yz = rotation.y * z2, zz = rotation.z * z2;", + " float wx = rotation.w * x2, wy = rotation.w * y2, wz = rotation.w * z2;", + " float sx = size, sy = size, sz = size;", + "", + " mat4 particleMatrix = mat4(( 1.0 - ( yy + zz ) ) * sx, ( xy + wz ) * sx, ( xz - wy ) * sx, 0.0, // 1. column", + " ( xy - wz ) * sy, ( 1.0 - ( xx + zz ) ) * sy, ( yz + wx ) * sy, 0.0, // 2. column", + " ( xz + wy ) * sz, ( yz - wx ) * sz, ( 1.0 - ( xx + yy ) ) * sz, 0.0, // 3. column", + " offset.x, offset.y, offset.z, 1.0);", + "", + "\t#include ", + "\t#include ", + "\t#include ", + "\t#include ", + "\t#include ", + "\t#include ", + "", + "\t// replace defaultnormal_vertex", + "\tvec3 transformedNormal = objectNormal;", + " mat3 m = mat3( particleMatrix );", + " transformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );", + " transformedNormal = m * transformedNormal;", + " transformedNormal = normalMatrix * transformedNormal;", + " #ifdef FLIP_SIDED", + " transformedNormal = - transformedNormal;", + " #endif", + " #ifdef USE_TANGENT", + " vec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;", + " #ifdef FLIP_SIDED", + " transformedTangent = - transformedTangent;", + " #endif", + " #endif", + "", + "\t#include ", + "\t#include ", + "\t#include ", + "\t#include ", + "\t#include ", + "", + "\t// replace include ", + " vec4 mvPosition = vec4( transformed, 1.0 );", + " mvPosition = modelViewMatrix * (particleMatrix * mvPosition);", + "\tgl_Position = projectionMatrix * mvPosition;", + "", + "\t#include ", + "\t#include ", + "\t", + "\tvViewPosition = - mvPosition.xyz;", + "\t", + "\t#include ", + "\t#include ", + "\t#include ", + "#ifdef USE_TRANSMISSION", + "\tvWorldPosition = worldPosition.xyz;", + "#endif", + "}", + "`;", + "", + "var stretched_bb_particle_vert = `", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "attribute vec3 offset;", + "attribute float rotation;", + "attribute float size;", + "attribute vec4 velocity;", + "attribute float uvTile;", + "", + "#ifdef UV_TILE", + "uniform vec2 tileCount;", + "#endif", + "", + "uniform float speedFactor;", + "", + "void main() {", + "", + " ${uv_vertex_tile}", + " ", + " float lengthFactor = velocity.w;", + "#ifdef USE_SKEW", + " vec4 mvPosition = modelViewMatrix * vec4( offset, 1.0 );", + " vec3 viewVelocity = normalMatrix * velocity.xyz;", + "", + " vec3 scaledPos = vec3(position.xy * size, position.z);", + " float vlength = length(viewVelocity);", + " vec3 projVelocity = dot(scaledPos, viewVelocity) * viewVelocity / vlength;", + " mvPosition.xyz += scaledPos + projVelocity * (speedFactor / size + lengthFactor / vlength);", + "#else", + " vec4 mvPosition = modelViewMatrix * vec4( offset, 1.0 );", + " vec3 viewVelocity = normalMatrix * velocity.xyz;", + " float vlength = length(viewVelocity); ", + " mvPosition.xyz += position.y * normalize(cross(mvPosition.xyz, viewVelocity)) * size; // switch the cross to match unity implementation", + " mvPosition.xyz -= (position.x + 0.5) * viewVelocity * (1.0 + lengthFactor / vlength) * size; // minus position.x to match unity implementation", + "#endif", + "\tvColor = color;", + "\tgl_Position = projectionMatrix * mvPosition;", + "\t#include ", + "\t#include ", + "}", + "`;", + "", + "function getMaterialUVChannelName(value) {", + " if (value === 0)", + " return 'uv';", + " return `uv${value}`;", + "}", + "", + "new THREE.Vector3(0, 0, 1);", + "class SpriteBatch extends VFXBatch {", + " constructor(settings) {", + " super(settings);", + " this.vector_ = new THREE.Vector3();", + " this.vector2_ = new THREE.Vector3();", + " this.vector3_ = new THREE.Vector3();", + " this.quaternion_ = new THREE.Quaternion();", + " this.quaternion2_ = new THREE.Quaternion();", + " this.quaternion3_ = new THREE.Quaternion();", + " this.rotationMat_ = new THREE.Matrix3();", + " this.rotationMat2_ = new THREE.Matrix3();", + " this.maxParticles = 1000;", + " this.setupBuffers();", + " this.rebuildMaterial();", + " }", + " buildExpandableBuffers() {", + " this.offsetBuffer = new THREE.InstancedBufferAttribute(new Float32Array(this.maxParticles * 3), 3);", + " this.offsetBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('offset', this.offsetBuffer);", + " this.colorBuffer = new THREE.InstancedBufferAttribute(new Float32Array(this.maxParticles * 4), 4);", + " this.colorBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('color', this.colorBuffer);", + " if (this.settings.renderMode === RenderMode.Mesh) {", + " this.rotationBuffer = new THREE.InstancedBufferAttribute(new Float32Array(this.maxParticles * 4), 4);", + " this.rotationBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('rotation', this.rotationBuffer);", + " }", + " else if (this.settings.renderMode === RenderMode.BillBoard ||", + " this.settings.renderMode === RenderMode.HorizontalBillBoard ||", + " this.settings.renderMode === RenderMode.VerticalBillBoard ||", + " this.settings.renderMode === RenderMode.StretchedBillBoard) {", + " this.rotationBuffer = new THREE.InstancedBufferAttribute(new Float32Array(this.maxParticles), 1);", + " this.rotationBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('rotation', this.rotationBuffer);", + " }", + " this.sizeBuffer = new THREE.InstancedBufferAttribute(new Float32Array(this.maxParticles), 1);", + " this.sizeBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('size', this.sizeBuffer);", + " this.uvTileBuffer = new THREE.InstancedBufferAttribute(new Float32Array(this.maxParticles), 1);", + " this.uvTileBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('uvTile', this.uvTileBuffer);", + " if (this.settings.renderMode === RenderMode.StretchedBillBoard) {", + " this.velocityBuffer = new THREE.InstancedBufferAttribute(new Float32Array(this.maxParticles * 4), 4);", + " this.velocityBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('velocity', this.velocityBuffer);", + " }", + " }", + " setupBuffers() {", + " if (this.geometry)", + " this.geometry.dispose();", + " this.geometry = new THREE.InstancedBufferGeometry();", + " this.geometry.setIndex(this.settings.instancingGeometry.getIndex());", + " if (this.settings.instancingGeometry.hasAttribute('normal')) {", + " this.geometry.setAttribute('normal', this.settings.instancingGeometry.getAttribute('normal'));", + " }", + " this.geometry.setAttribute('position', this.settings.instancingGeometry.getAttribute('position'));", + " this.geometry.setAttribute('uv', this.settings.instancingGeometry.getAttribute('uv'));", + " this.buildExpandableBuffers();", + " }", + " expandBuffers(target) {", + " while (target >= this.maxParticles) {", + " this.maxParticles *= 2;", + " }", + " this.setupBuffers();", + " }", + " rebuildMaterial() {", + " this.layers.mask = this.settings.layers.mask;", + " let uniforms;", + " const defines = {};", + " if (this.settings.material.type === 'MeshStandardMaterial' ||", + " this.settings.material.type === 'MeshPhysicalMaterial') {", + " const mat = this.settings.material;", + " uniforms = THREE.UniformsUtils.merge([", + " THREE.UniformsLib.common,", + " THREE.UniformsLib.envmap,", + " THREE.UniformsLib.aomap,", + " THREE.UniformsLib.lightmap,", + " THREE.UniformsLib.emissivemap,", + " THREE.UniformsLib.bumpmap,", + " THREE.UniformsLib.normalmap,", + " THREE.UniformsLib.displacementmap,", + " THREE.UniformsLib.roughnessmap,", + " THREE.UniformsLib.metalnessmap,", + " THREE.UniformsLib.fog,", + " THREE.UniformsLib.lights,", + " {", + " emissive: { value: new THREE.Color(0x000000) },", + " roughness: { value: 1.0 },", + " metalness: { value: 0.0 },", + " envMapIntensity: { value: 1 },", + " },", + " ]);", + " uniforms['diffuse'].value = mat.color;", + " uniforms['opacity'].value = mat.opacity;", + " uniforms['emissive'].value = mat.emissive;", + " uniforms['roughness'].value = mat.roughness;", + " uniforms['metalness'].value = mat.metalness;", + " if (mat.envMap) {", + " uniforms['envMap'].value = mat.envMap;", + " uniforms['envMapIntensity'].value = mat.envMapIntensity;", + " }", + " if (mat.normalMap) {", + " uniforms['normalMap'].value = mat.normalMap;", + " uniforms['normalScale'].value = mat.normalScale;", + " }", + " if (mat.roughnessMap) {", + " uniforms['roughnessMap'].value = mat.roughnessMap;", + " }", + " if (mat.metalnessMap) {", + " uniforms['metalnessMap'].value = mat.metalnessMap;", + " }", + " if (mat.map) {", + " uniforms['map'] = new THREE.Uniform(mat.map);", + " }", + " }", + " else {", + " uniforms = {};", + " uniforms['map'] = new THREE.Uniform(this.settings.material.map);", + " }", + " if (this.settings.material.alphaTest) {", + " defines['USE_ALPHATEST'] = '';", + " uniforms['alphaTest'] = new THREE.Uniform(this.settings.material.alphaTest);", + " }", + " defines['USE_UV'] = '';", + " const uTileCount = this.settings.uTileCount;", + " const vTileCount = this.settings.vTileCount;", + " if (uTileCount > 1 || vTileCount > 1) {", + " defines['UV_TILE'] = '';", + " uniforms['tileCount'] = new THREE.Uniform(new THREE.Vector2(uTileCount, vTileCount));", + " }", + " if (this.settings.material.defines &&", + " this.settings.material.defines['USE_COLOR_AS_ALPHA'] !== undefined) {", + " defines['USE_COLOR_AS_ALPHA'] = '';", + " }", + " if (this.settings.material.normalMap) {", + " defines['USE_NORMALMAP'] = '';", + " defines['NORMALMAP_UV'] = getMaterialUVChannelName(this.settings.material.normalMap.channel);", + " uniforms['normalMapTransform'] = new THREE.Uniform(new THREE.Matrix3().copy(this.settings.material.normalMap.matrix));", + " }", + " if (this.settings.material.map) {", + " defines['USE_MAP'] = '';", + " defines['MAP_UV'] = getMaterialUVChannelName(this.settings.material.map.channel);", + " uniforms['mapTransform'] = new THREE.Uniform(new THREE.Matrix3().copy(this.settings.material.map.matrix));", + " }", + " defines['USE_COLOR_ALPHA'] = '';", + " let needLights = false;", + " if (this.settings.renderMode === RenderMode.BillBoard ||", + " this.settings.renderMode === RenderMode.VerticalBillBoard ||", + " this.settings.renderMode === RenderMode.HorizontalBillBoard ||", + " this.settings.renderMode === RenderMode.Mesh) {", + " let vertexShader;", + " let fragmentShader;", + " if (this.settings.renderMode === RenderMode.Mesh) {", + " if (this.settings.material.type === 'MeshStandardMaterial' ||", + " this.settings.material.type === 'MeshPhysicalMaterial') {", + " defines['USE_COLOR'] = '';", + " vertexShader = local_particle_physics_vert;", + " fragmentShader = particle_physics_frag;", + " needLights = true;", + " }", + " else {", + " vertexShader = local_particle_vert;", + " fragmentShader = particle_frag;", + " }", + " }", + " else {", + " vertexShader = particle_vert;", + " fragmentShader = particle_frag;", + " }", + " if (this.settings.renderMode === RenderMode.VerticalBillBoard) {", + " defines['VERTICAL'] = '';", + " }", + " else if (this.settings.renderMode === RenderMode.HorizontalBillBoard) {", + " defines['HORIZONTAL'] = '';", + " }", + " this.material = new THREE.ShaderMaterial({", + " uniforms: uniforms,", + " defines: defines,", + " vertexShader: vertexShader,", + " fragmentShader: fragmentShader,", + " transparent: this.settings.material.transparent,", + " depthWrite: !this.settings.material.transparent,", + " blending: this.settings.material.blending,", + " side: this.settings.material.side,", + " alphaTest: this.settings.material.alphaTest,", + " lights: needLights,", + " });", + " }", + " else if (this.settings.renderMode === RenderMode.StretchedBillBoard) {", + " uniforms['speedFactor'] = new THREE.Uniform(1.0);", + " this.material = new THREE.ShaderMaterial({", + " uniforms: uniforms,", + " defines: defines,", + " vertexShader: stretched_bb_particle_vert,", + " fragmentShader: particle_frag,", + " transparent: this.settings.material.transparent,", + " depthWrite: !this.settings.material.transparent,", + " blending: this.settings.material.blending,", + " side: this.settings.material.side,", + " alphaTest: this.settings.material.alphaTest,", + " });", + " }", + " else {", + " throw new Error('render mode unavailable');", + " }", + " }", + " update() {", + " let index = 0;", + " let particleCount = 0;", + " this.systems.forEach((system) => {", + " particleCount += system.particleNum;", + " });", + " if (particleCount > this.maxParticles) {", + " this.expandBuffers(particleCount);", + " }", + " this.systems.forEach((system) => {", + " const particles = system.particles;", + " const particleNum = system.particleNum;", + " const rotation = this.quaternion2_;", + " const translation = this.vector2_;", + " const scale = this.vector3_;", + " system.emitter.matrixWorld.decompose(translation, rotation, scale);", + " this.rotationMat_.setFromMatrix4(system.emitter.matrixWorld);", + " for (let j = 0; j < particleNum; j++ , index++) {", + " const particle = particles[j];", + " if (this.settings.renderMode === RenderMode.Mesh) {", + " let q;", + " if (system.worldSpace) {", + " q = particle.rotation;", + " }", + " else {", + " let parentQ;", + " if (particle.parentMatrix) {", + " parentQ = this.quaternion3_.setFromRotationMatrix(particle.parentMatrix);", + " }", + " else {", + " parentQ = rotation;", + " }", + " q = this.quaternion_;", + " q.copy(particle.rotation).multiply(parentQ);", + " }", + " this.rotationBuffer.setXYZW(index, q.x, q.y, q.z, q.w);", + " }", + " else if (this.settings.renderMode === RenderMode.StretchedBillBoard ||", + " this.settings.renderMode === RenderMode.VerticalBillBoard ||", + " this.settings.renderMode === RenderMode.HorizontalBillBoard ||", + " this.settings.renderMode === RenderMode.BillBoard) {", + " this.rotationBuffer.setX(index, particle.rotation);", + " }", + " let vec;", + " if (system.worldSpace) {", + " vec = particle.position;", + " }", + " else {", + " vec = this.vector_;", + " if (particle.parentMatrix) {", + " vec.copy(particle.position).applyMatrix4(particle.parentMatrix);", + " }", + " else {", + " vec.copy(particle.position).applyMatrix4(system.emitter.matrixWorld);", + " }", + " }", + " this.offsetBuffer.setXYZ(index, vec.x, vec.y, vec.z);", + " this.colorBuffer.setXYZW(index, particle.color.x, particle.color.y, particle.color.z, particle.color.w);", + " if (system.worldSpace) {", + " this.sizeBuffer.setX(index, particle.size);", + " }", + " else {", + " if (particle.parentMatrix) {", + " this.sizeBuffer.setX(index, particle.size);", + " }", + " else {", + " this.sizeBuffer.setX(index, (particle.size * (Math.abs(scale.x) + Math.abs(scale.y) + Math.abs(scale.z))) / 3);", + " }", + " }", + " this.uvTileBuffer.setX(index, particle.uvTile);", + " if (this.settings.renderMode === RenderMode.StretchedBillBoard && this.velocityBuffer) {", + " let speedFactor = system.rendererEmitterSettings.speedFactor;", + " if (speedFactor === 0)", + " speedFactor = 0.001;", + " const lengthFactor = system.rendererEmitterSettings.lengthFactor;", + " let vec;", + " if (system.worldSpace) {", + " vec = particle.velocity;", + " }", + " else {", + " vec = this.vector_;", + " if (particle.parentMatrix) {", + " this.rotationMat2_.setFromMatrix4(particle.parentMatrix);", + " vec.copy(particle.velocity).applyMatrix3(this.rotationMat2_);", + " }", + " else {", + " vec.copy(particle.velocity).applyMatrix3(this.rotationMat_);", + " }", + " }", + " this.velocityBuffer.setXYZW(index, vec.x * speedFactor, vec.y * speedFactor, vec.z * speedFactor, lengthFactor);", + " }", + " }", + " });", + " this.geometry.instanceCount = index;", + " if (index > 0) {", + " this.offsetBuffer.clearUpdateRanges();", + " this.offsetBuffer.addUpdateRange(0, index * 3);", + " this.offsetBuffer.needsUpdate = true;", + " this.sizeBuffer.clearUpdateRanges();", + " this.sizeBuffer.addUpdateRange(0, index);", + " this.sizeBuffer.needsUpdate = true;", + " this.colorBuffer.clearUpdateRanges();", + " this.colorBuffer.addUpdateRange(0, index * 4);", + " this.colorBuffer.needsUpdate = true;", + " this.uvTileBuffer.clearUpdateRanges();", + " this.uvTileBuffer.addUpdateRange(0, index);", + " this.uvTileBuffer.needsUpdate = true;", + " if (this.settings.renderMode === RenderMode.StretchedBillBoard && this.velocityBuffer) {", + " this.velocityBuffer.clearUpdateRanges();", + " this.velocityBuffer.addUpdateRange(0, index * 4);", + " this.velocityBuffer.needsUpdate = true;", + " }", + " if (this.settings.renderMode === RenderMode.Mesh) {", + " this.rotationBuffer.clearUpdateRanges();", + " this.rotationBuffer.addUpdateRange(0, index * 4);", + " this.rotationBuffer.needsUpdate = true;", + " }", + " else if (this.settings.renderMode === RenderMode.StretchedBillBoard ||", + " this.settings.renderMode === RenderMode.HorizontalBillBoard ||", + " this.settings.renderMode === RenderMode.VerticalBillBoard ||", + " this.settings.renderMode === RenderMode.BillBoard) {", + " this.rotationBuffer.clearUpdateRanges();", + " this.rotationBuffer.addUpdateRange(0, index);", + " this.rotationBuffer.needsUpdate = true;", + " }", + " }", + " }", + " dispose() {", + " this.geometry.dispose();", + " }", + "}", + "", + "var trail_frag = `", + "", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "uniform sampler2D alphaMap;", + "uniform float useAlphaMap;", + "uniform float visibility;", + "uniform float alphaTest;", + "uniform vec2 repeat;", + "", + "varying vec4 vColor;", + " ", + "void main() {", + " #include ", + " #include ", + "", + " vec4 c = vColor;", + " ", + " #ifdef USE_MAP", + " #ifdef USE_COLOR_AS_ALPHA", + " vec4 tex = texture2D( map, vUv * repeat );", + " c *= vec4(tex.rgb, tex.r);", + " #else", + " c *= texture2D( map, vUv * repeat );", + " #endif", + " #endif", + " if( useAlphaMap == 1. ) c.a *= texture2D( alphaMap, vUv * repeat ).a;", + " if( c.a < alphaTest ) discard;", + " gl_FragColor = c;", + "", + " #include ", + " #include ", + "}`;", + "", + "var trail_vert = `", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "#include ", + "", + "attribute vec3 previous;", + "attribute vec3 next;", + "attribute float side;", + "attribute float width;", + "", + "uniform vec2 resolution;", + "uniform float lineWidth;", + "uniform float sizeAttenuation;", + " ", + "vec2 fix(vec4 i, float aspect) {", + " vec2 res = i.xy / i.w;", + " res.x *= aspect;", + " return res;", + "}", + " ", + "void main() {", + "", + " ${uv_vertex_tile}", + " ", + " float aspect = resolution.x / resolution.y;", + "", + " vColor = color;", + "", + " mat4 m = projectionMatrix * modelViewMatrix;", + " vec4 finalPosition = m * vec4( position, 1.0 );", + " vec4 prevPos = m * vec4( previous, 1.0 );", + " vec4 nextPos = m * vec4( next, 1.0 );", + "", + " vec2 currentP = fix( finalPosition, aspect );", + " vec2 prevP = fix( prevPos, aspect );", + " vec2 nextP = fix( nextPos, aspect );", + "", + " float w = lineWidth * width;", + "", + " vec2 dir;", + " if( nextP == currentP ) dir = normalize( currentP - prevP );", + " else if( prevP == currentP ) dir = normalize( nextP - currentP );", + " else {", + " vec2 dir1 = normalize( currentP - prevP );", + " vec2 dir2 = normalize( nextP - currentP );", + " dir = normalize( dir1 + dir2 );", + "", + " vec2 perp = vec2( -dir1.y, dir1.x );", + " vec2 miter = vec2( -dir.y, dir.x );", + " //w = clamp( w / dot( miter, perp ), 0., 4., * lineWidth * width );", + "", + " }", + "", + " //vec2 normal = ( cross( vec3( dir, 0. ) vec3( 0., 0., 1. ) ) ).xy;", + " vec4 normal = vec4( -dir.y, dir.x, 0., 1. );", + " normal.xy *= .5 * w;", + " normal *= projectionMatrix;", + " if( sizeAttenuation == 0. ) {", + " normal.xy *= finalPosition.w;", + " normal.xy /= ( vec4( resolution, 0., 1. ) * projectionMatrix ).xy;", + " }", + "", + " finalPosition.xy += normal.xy * side;", + "", + " gl_Position = finalPosition;", + "", + "\t#include ", + "\t#include ", + "\t", + " vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", + " ", + "\t#include ", + "}`;", + "", + "new THREE.Vector3(0, 0, 1);", + "class TrailBatch extends VFXBatch {", + " constructor(settings) {", + " super(settings);", + " this.vector_ = new THREE.Vector3();", + " this.vector2_ = new THREE.Vector3();", + " this.vector3_ = new THREE.Vector3();", + " this.quaternion_ = new THREE.Quaternion();", + " this.maxParticles = 10000;", + " this.setupBuffers();", + " this.rebuildMaterial();", + " }", + " setupBuffers() {", + " if (this.geometry)", + " this.geometry.dispose();", + " this.geometry = new THREE.BufferGeometry();", + " this.indexBuffer = new THREE.BufferAttribute(new Uint32Array(this.maxParticles * 6), 1);", + " this.indexBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setIndex(this.indexBuffer);", + " this.positionBuffer = new THREE.BufferAttribute(new Float32Array(this.maxParticles * 6), 3);", + " this.positionBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('position', this.positionBuffer);", + " this.previousBuffer = new THREE.BufferAttribute(new Float32Array(this.maxParticles * 6), 3);", + " this.previousBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('previous', this.previousBuffer);", + " this.nextBuffer = new THREE.BufferAttribute(new Float32Array(this.maxParticles * 6), 3);", + " this.nextBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('next', this.nextBuffer);", + " this.widthBuffer = new THREE.BufferAttribute(new Float32Array(this.maxParticles * 2), 1);", + " this.widthBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('width', this.widthBuffer);", + " this.sideBuffer = new THREE.BufferAttribute(new Float32Array(this.maxParticles * 2), 1);", + " this.sideBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('side', this.sideBuffer);", + " this.uvBuffer = new THREE.BufferAttribute(new Float32Array(this.maxParticles * 4), 2);", + " this.uvBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('uv', this.uvBuffer);", + " this.colorBuffer = new THREE.BufferAttribute(new Float32Array(this.maxParticles * 8), 4);", + " this.colorBuffer.setUsage(THREE.DynamicDrawUsage);", + " this.geometry.setAttribute('color', this.colorBuffer);", + " }", + " expandBuffers(target) {", + " while (target >= this.maxParticles) {", + " this.maxParticles *= 2;", + " }", + " this.setupBuffers();", + " }", + " rebuildMaterial() {", + " this.layers.mask = this.settings.layers.mask;", + " const uniforms = {", + " lineWidth: { value: 1 },", + " map: { value: null },", + " useMap: { value: 0 },", + " alphaMap: { value: null },", + " useAlphaMap: { value: 0 },", + " resolution: { value: new THREE.Vector2(1, 1) },", + " sizeAttenuation: { value: 1 },", + " visibility: { value: 1 },", + " alphaTest: { value: 0 },", + " repeat: { value: new THREE.Vector2(1, 1) },", + " };", + " const defines = {};", + " defines['USE_UV'] = '';", + " defines['USE_COLOR_ALPHA'] = '';", + " if (this.settings.material.map) {", + " defines['USE_MAP'] = '';", + " defines['MAP_UV'] = getMaterialUVChannelName(this.settings.material.map.channel);", + " uniforms['map'] = new THREE.Uniform(this.settings.material.map);", + " uniforms['mapTransform'] = new THREE.Uniform(new THREE.Matrix3().copy(this.settings.material.map.matrix));", + " }", + " if (this.settings.material.defines &&", + " this.settings.material.defines['USE_COLOR_AS_ALPHA'] !== undefined) {", + " defines['USE_COLOR_AS_ALPHA'] = '';", + " }", + " if (this.settings.renderMode === RenderMode.Trail) {", + " this.material = new THREE.ShaderMaterial({", + " uniforms: uniforms,", + " defines: defines,", + " vertexShader: trail_vert,", + " fragmentShader: trail_frag,", + " transparent: this.settings.material.transparent,", + " depthWrite: !this.settings.material.transparent,", + " side: this.settings.material.side,", + " blending: this.settings.material.blending || THREE.AdditiveBlending,", + " });", + " }", + " else {", + " throw new Error('render mode unavailable');", + " }", + " }", + " update() {", + " let index = 0;", + " let triangles = 0;", + " let particleCount = 0;", + " this.systems.forEach((system) => {", + " for (let j = 0; j < system.particleNum; j++) {", + " particleCount += system.particles[j].previous.length * 2;", + " }", + " });", + " if (particleCount > this.maxParticles) {", + " this.expandBuffers(particleCount);", + " }", + " this.systems.forEach((system) => {", + " const rotation = this.quaternion_;", + " const translation = this.vector2_;", + " const scale = this.vector3_;", + " system.emitter.matrixWorld.decompose(translation, rotation, scale);", + " const particles = system.particles;", + " const particleNum = system.particleNum;", + " const uTileCount = this.settings.uTileCount;", + " const vTileCount = this.settings.vTileCount;", + " const tileWidth = 1 / uTileCount;", + " const tileHeight = 1 / vTileCount;", + " for (let j = 0; j < particleNum; j++) {", + " const particle = particles[j];", + " const col = particle.uvTile % vTileCount;", + " const row = Math.floor(particle.uvTile / vTileCount + 0.001);", + " const iter = particle.previous.values();", + " let curIter = iter.next();", + " let previous = curIter.value;", + " let current = previous;", + " if (!curIter.done)", + " curIter = iter.next();", + " let next;", + " if (curIter.value !== undefined) {", + " next = curIter.value;", + " }", + " else {", + " next = current;", + " }", + " for (let i = 0; i < particle.previous.length; i++ , index += 2) {", + " this.positionBuffer.setXYZ(index, current.position.x, current.position.y, current.position.z);", + " this.positionBuffer.setXYZ(index + 1, current.position.x, current.position.y, current.position.z);", + " if (system.worldSpace) {", + " this.positionBuffer.setXYZ(index, current.position.x, current.position.y, current.position.z);", + " this.positionBuffer.setXYZ(index + 1, current.position.x, current.position.y, current.position.z);", + " }", + " else {", + " if (particle.parentMatrix) {", + " this.vector_.copy(current.position).applyMatrix4(particle.parentMatrix);", + " }", + " else {", + " this.vector_.copy(current.position).applyMatrix4(system.emitter.matrixWorld);", + " }", + " this.positionBuffer.setXYZ(index, this.vector_.x, this.vector_.y, this.vector_.z);", + " this.positionBuffer.setXYZ(index + 1, this.vector_.x, this.vector_.y, this.vector_.z);", + " }", + " if (system.worldSpace) {", + " this.previousBuffer.setXYZ(index, previous.position.x, previous.position.y, previous.position.z);", + " this.previousBuffer.setXYZ(index + 1, previous.position.x, previous.position.y, previous.position.z);", + " }", + " else {", + " if (particle.parentMatrix) {", + " this.vector_.copy(previous.position).applyMatrix4(particle.parentMatrix);", + " }", + " else {", + " this.vector_.copy(previous.position).applyMatrix4(system.emitter.matrixWorld);", + " }", + " this.previousBuffer.setXYZ(index, this.vector_.x, this.vector_.y, this.vector_.z);", + " this.previousBuffer.setXYZ(index + 1, this.vector_.x, this.vector_.y, this.vector_.z);", + " }", + " if (system.worldSpace) {", + " this.nextBuffer.setXYZ(index, next.position.x, next.position.y, next.position.z);", + " this.nextBuffer.setXYZ(index + 1, next.position.x, next.position.y, next.position.z);", + " }", + " else {", + " if (particle.parentMatrix) {", + " this.vector_.copy(next.position).applyMatrix4(particle.parentMatrix);", + " }", + " else {", + " this.vector_.copy(next.position).applyMatrix4(system.emitter.matrixWorld);", + " }", + " this.nextBuffer.setXYZ(index, this.vector_.x, this.vector_.y, this.vector_.z);", + " this.nextBuffer.setXYZ(index + 1, this.vector_.x, this.vector_.y, this.vector_.z);", + " }", + " this.sideBuffer.setX(index, -1);", + " this.sideBuffer.setX(index + 1, 1);", + " if (system.worldSpace) {", + " this.widthBuffer.setX(index, current.size);", + " this.widthBuffer.setX(index + 1, current.size);", + " }", + " else {", + " if (particle.parentMatrix) {", + " this.widthBuffer.setX(index, current.size);", + " this.widthBuffer.setX(index + 1, current.size);", + " }", + " else {", + " const objectScale = (Math.abs(scale.x) + Math.abs(scale.y) + Math.abs(scale.z)) / 3;", + " this.widthBuffer.setX(index, current.size * objectScale);", + " this.widthBuffer.setX(index + 1, current.size * objectScale);", + " }", + " }", + " this.uvBuffer.setXY(index, (i / particle.previous.length + col) * tileWidth, (vTileCount - row - 1) * tileHeight);", + " this.uvBuffer.setXY(index + 1, (i / particle.previous.length + col) * tileWidth, (vTileCount - row) * tileHeight);", + " this.colorBuffer.setXYZW(index, current.color.x, current.color.y, current.color.z, current.color.w);", + " this.colorBuffer.setXYZW(index + 1, current.color.x, current.color.y, current.color.z, current.color.w);", + " if (i + 1 < particle.previous.length) {", + " this.indexBuffer.setX(triangles * 3, index);", + " this.indexBuffer.setX(triangles * 3 + 1, index + 1);", + " this.indexBuffer.setX(triangles * 3 + 2, index + 2);", + " triangles++;", + " this.indexBuffer.setX(triangles * 3, index + 2);", + " this.indexBuffer.setX(triangles * 3 + 1, index + 1);", + " this.indexBuffer.setX(triangles * 3 + 2, index + 3);", + " triangles++;", + " }", + " previous = current;", + " current = next;", + " if (!curIter.done) {", + " curIter = iter.next();", + " if (curIter.value !== undefined) {", + " next = curIter.value;", + " }", + " }", + " }", + " }", + " });", + " this.positionBuffer.clearUpdateRanges();", + " this.positionBuffer.addUpdateRange(0, index * 3);", + " this.positionBuffer.needsUpdate = true;", + " this.previousBuffer.clearUpdateRanges();", + " this.previousBuffer.addUpdateRange(0, index * 3);", + " this.previousBuffer.needsUpdate = true;", + " this.nextBuffer.clearUpdateRanges();", + " this.nextBuffer.addUpdateRange(0, index * 3);", + " this.nextBuffer.needsUpdate = true;", + " this.sideBuffer.clearUpdateRanges();", + " this.sideBuffer.addUpdateRange(0, index);", + " this.sideBuffer.needsUpdate = true;", + " this.widthBuffer.clearUpdateRanges();", + " this.widthBuffer.addUpdateRange(0, index);", + " this.widthBuffer.needsUpdate = true;", + " this.uvBuffer.clearUpdateRanges();", + " this.uvBuffer.addUpdateRange(0, index * 2);", + " this.uvBuffer.needsUpdate = true;", + " this.colorBuffer.clearUpdateRanges();", + " this.colorBuffer.addUpdateRange(0, index * 4);", + " this.colorBuffer.needsUpdate = true;", + " this.indexBuffer.clearUpdateRanges();", + " this.indexBuffer.addUpdateRange(0, triangles * 3);", + " this.indexBuffer.needsUpdate = true;", + " this.geometry.setDrawRange(0, triangles * 3);", + " }", + " dispose() {", + " this.geometry.dispose();", + " }", + "}", + "", + "class BatchedRenderer extends THREE.Object3D {", + " constructor() {", + " super();", + " this.batches = [];", + " this.systemToBatchIndex = new Map();", + " this.type = 'BatchedRenderer';", + " }", + " static equals(a, b) {", + " return (a.material.side === b.material.side &&", + " a.material.blending === b.material.blending &&", + " a.material.transparent === b.material.transparent &&", + " a.material.type === b.material.type &&", + " a.material.alphaTest === b.material.alphaTest &&", + " a.material.map === b.material.map &&", + " a.renderMode === b.renderMode &&", + " a.uTileCount === b.uTileCount &&", + " a.vTileCount === b.vTileCount &&", + " a.instancingGeometry === b.instancingGeometry &&", + " a.renderOrder === b.renderOrder &&", + " a.layers.mask === b.layers.mask);", + " }", + " addSystem(system) {", + " system._renderer = this;", + " const settings = system.getRendererSettings();", + " for (let i = 0; i < this.batches.length; i++) {", + " if (BatchedRenderer.equals(this.batches[i].settings, settings)) {", + " this.batches[i].addSystem(system);", + " this.systemToBatchIndex.set(system, i);", + " return;", + " }", + " }", + " let batch;", + " switch (settings.renderMode) {", + " case RenderMode.Trail:", + " batch = new TrailBatch(settings);", + " break;", + " case RenderMode.Mesh:", + " case RenderMode.BillBoard:", + " case RenderMode.VerticalBillBoard:", + " case RenderMode.HorizontalBillBoard:", + " case RenderMode.StretchedBillBoard:", + " batch = new SpriteBatch(settings);", + " break;", + " }", + " batch.addSystem(system);", + " this.batches.push(batch);", + " this.systemToBatchIndex.set(system, this.batches.length - 1);", + " this.add(batch);", + " }", + " deleteSystem(system) {", + " const batchIndex = this.systemToBatchIndex.get(system);", + " if (batchIndex != undefined) {", + " this.batches[batchIndex].removeSystem(system);", + " this.systemToBatchIndex.delete(system);", + " }", + " }", + " updateSystem(system) {", + " this.deleteSystem(system);", + " this.addSystem(system);", + " }", + " update(delta) {", + " this.systemToBatchIndex.forEach((value, ps) => {", + " ps.update(delta);", + " });", + " for (let i = 0; i < this.batches.length; i++) {", + " this.batches[i].update();", + " }", + " }", + "}", + "", + "const BatchedParticleRenderer = BatchedRenderer;", + "", + "class QuarksLoader extends THREE.ObjectLoader {", + " constructor(manager) {", + " super(manager);", + " }", + " linkReference(object) {", + " const objectsMap = {};", + " object.traverse(function (child) {", + " objectsMap[child.uuid] = child;", + " });", + " object.traverse(function (child) {", + " if (child.type === 'ParticleEmitter') {", + " const system = child.system;", + " system.emitterShape;", + " for (let i = 0; i < system.behaviors.length; i++) {", + " if (system.behaviors[i] instanceof EmitSubParticleSystem) {", + " system.behaviors[i].subParticleSystem = objectsMap[system.behaviors[i].subParticleSystem];", + " }", + " }", + " }", + " });", + " }", + " parse(json, onLoad) {", + " const object = super.parse(json, onLoad);", + " this.linkReference(object);", + " return object;", + " }", + " parseObject(data, geometries, materials, textures, animations) {", + " let object;", + " function getGeometry(name) {", + " if (geometries[name] === undefined) {", + " console.warn('THREE.ObjectLoader: Undefined geometry', name);", + " }", + " return geometries[name];", + " }", + " function getMaterial(name) {", + " if (name === undefined)", + " return undefined;", + " if (Array.isArray(name)) {", + " const array = [];", + " for (let i = 0, l = name.length; i < l; i++) {", + " const uuid = name[i];", + " if (materials[uuid] === undefined) {", + " console.warn('THREE.ObjectLoader: Undefined material', uuid);", + " }", + " array.push(materials[uuid]);", + " }", + " return array;", + " }", + " if (materials[name] === undefined) {", + " console.warn('THREE.ObjectLoader: Undefined material', name);", + " }", + " return materials[name];", + " }", + " function getTexture(uuid) {", + " if (textures[uuid] === undefined) {", + " console.warn('THREE.ObjectLoader: Undefined texture', uuid);", + " }", + " return textures[uuid];", + " }", + " let geometry, material;", + " const meta = {", + " textures: textures,", + " geometries: geometries,", + " materials: materials,", + " };", + " const dependencies = {};", + " switch (data.type) {", + " case 'ParticleEmitter':", + " object = ParticleSystem.fromJSON(data.ps, meta, dependencies).emitter;", + " break;", + " case 'Scene':", + " object = new THREE.Scene();", + " if (data.background !== undefined) {", + " if (Number.isInteger(data.background)) {", + " object.background = new THREE.Color(data.background);", + " }", + " else {", + " object.background = getTexture(data.background);", + " }", + " }", + " if (data.environment !== undefined) {", + " object.environment = getTexture(data.environment);", + " }", + " if (data.fog !== undefined) {", + " if (data.fog.type === 'Fog') {", + " object.fog = new THREE.Fog(data.fog.color, data.fog.near, data.fog.far);", + " }", + " else if (data.fog.type === 'FogExp2') {", + " object.fog = new THREE.FogExp2(data.fog.color, data.fog.density);", + " }", + " }", + " if (data.backgroundBlurriness !== undefined)", + " object.backgroundBlurriness = data.backgroundBlurriness;", + " break;", + " case 'PerspectiveCamera':", + " object = new THREE.PerspectiveCamera(data.fov, data.aspect, data.near, data.far);", + " if (data.focus !== undefined)", + " object.focus = data.focus;", + " if (data.zoom !== undefined)", + " object.zoom = data.zoom;", + " if (data.filmGauge !== undefined)", + " object.filmGauge = data.filmGauge;", + " if (data.filmOffset !== undefined)", + " object.filmOffset = data.filmOffset;", + " if (data.view !== undefined)", + " object.view = Object.assign({}, data.view);", + " break;", + " case 'OrthographicCamera':", + " object = new THREE.OrthographicCamera(data.left, data.right, data.top, data.bottom, data.near, data.far);", + " if (data.zoom !== undefined)", + " object.zoom = data.zoom;", + " if (data.view !== undefined)", + " object.view = Object.assign({}, data.view);", + " break;", + " case 'AmbientLight':", + " object = new THREE.AmbientLight(data.color, data.intensity);", + " break;", + " case 'DirectionalLight':", + " object = new THREE.DirectionalLight(data.color, data.intensity);", + " break;", + " case 'PointLight':", + " object = new THREE.PointLight(data.color, data.intensity, data.distance, data.decay);", + " break;", + " case 'RectAreaLight':", + " object = new THREE.RectAreaLight(data.color, data.intensity, data.width, data.height);", + " break;", + " case 'SpotLight':", + " object = new THREE.SpotLight(data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay);", + " break;", + " case 'HemisphereLight':", + " object = new THREE.HemisphereLight(data.color, data.groundColor, data.intensity);", + " break;", + " case 'LightProbe':", + " object = new THREE.LightProbe().fromJSON(data);", + " break;", + " case 'SkinnedMesh':", + " geometry = getGeometry(data.geometry);", + " material = getMaterial(data.material);", + " object = new THREE.SkinnedMesh(geometry, material);", + " if (data.bindMode !== undefined)", + " object.bindMode = data.bindMode;", + " if (data.bindMatrix !== undefined)", + " object.bindMatrix.fromArray(data.bindMatrix);", + " if (data.skeleton !== undefined)", + " object.skeleton = data.skeleton;", + " break;", + " case 'Mesh':", + " geometry = getGeometry(data.geometry);", + " material = getMaterial(data.material);", + " object = new THREE.Mesh(geometry, material);", + " break;", + " case 'InstancedMesh': {", + " geometry = getGeometry(data.geometry);", + " material = getMaterial(data.material);", + " const count = data.count;", + " const instanceMatrix = data.instanceMatrix;", + " const instanceColor = data.instanceColor;", + " object = new THREE.InstancedMesh(geometry, material, count);", + " object.instanceMatrix = new THREE.InstancedBufferAttribute(new Float32Array(instanceMatrix.array), 16);", + " if (instanceColor !== undefined)", + " object.instanceColor = new THREE.InstancedBufferAttribute(new Float32Array(instanceColor.array), instanceColor.itemSize);", + " break;", + " }", + " case 'LOD':", + " object = new THREE.LOD();", + " break;", + " case 'Line':", + " object = new THREE.Line(getGeometry(data.geometry), getMaterial(data.material));", + " break;", + " case 'LineLoop':", + " object = new THREE.LineLoop(getGeometry(data.geometry), getMaterial(data.material));", + " break;", + " case 'LineSegments':", + " object = new THREE.LineSegments(getGeometry(data.geometry), getMaterial(data.material));", + " break;", + " case 'PointCloud':", + " case 'Points':", + " object = new THREE.Points(getGeometry(data.geometry), getMaterial(data.material));", + " break;", + " case 'Sprite':", + " object = new THREE.Sprite(getMaterial(data.material));", + " break;", + " case 'Group':", + " object = new THREE.Group();", + " break;", + " case 'Bone':", + " object = new THREE.Bone();", + " break;", + " default:", + " object = new THREE.Object3D();", + " }", + " object.uuid = data.uuid;", + " if (data.name !== undefined)", + " object.name = data.name;", + " if (data.matrix !== undefined) {", + " object.matrix.fromArray(data.matrix);", + " if (data.matrixAutoUpdate !== undefined)", + " object.matrixAutoUpdate = data.matrixAutoUpdate;", + " if (object.matrixAutoUpdate)", + " object.matrix.decompose(object.position, object.quaternion, object.scale);", + " }", + " else {", + " if (data.position !== undefined)", + " object.position.fromArray(data.position);", + " if (data.rotation !== undefined)", + " object.rotation.fromArray(data.rotation);", + " if (data.quaternion !== undefined)", + " object.quaternion.fromArray(data.quaternion);", + " if (data.scale !== undefined)", + " object.scale.fromArray(data.scale);", + " }", + " if (data.castShadow !== undefined)", + " object.castShadow = data.castShadow;", + " if (data.receiveShadow !== undefined)", + " object.receiveShadow = data.receiveShadow;", + " if (data.shadow) {", + " if (data.shadow.bias !== undefined)", + " object.shadow.bias = data.shadow.bias;", + " if (data.shadow.normalBias !== undefined)", + " object.normalBias = data.shadow.normalBias;", + " if (data.shadow.radius !== undefined)", + " object.radius = data.shadow.radius;", + " if (data.shadow.mapSize !== undefined)", + " object.mapSize.fromArray(data.shadow.mapSize);", + " if (data.shadow.camera !== undefined) {", + " object.camera = this.parseObject(data.shadow.camera);", + " }", + " }", + " if (data.visible !== undefined)", + " object.visible = data.visible;", + " if (data.frustumCulled !== undefined)", + " object.frustumCulled = data.frustumCulled;", + " if (data.renderOrder !== undefined)", + " object.renderOrder = data.renderOrder;", + " if (data.userData !== undefined)", + " object.userData = data.userData;", + " if (data.layers !== undefined)", + " object.layers.mask = data.layers;", + " if (data.children !== undefined) {", + " const children = data.children;", + " for (let i = 0; i < children.length; i++) {", + " object.add(this.parseObject(children[i], geometries, materials, textures, animations));", + " }", + " }", + " if (data.animations !== undefined) {", + " const objectAnimations = data.animations;", + " for (let i = 0; i < objectAnimations.length; i++) {", + " const uuid = objectAnimations[i];", + " object.animations.push(animations[uuid]);", + " }", + " }", + " if (data.type === 'LOD') {", + " if (data.autoUpdate !== undefined)", + " object.autoUpdate = data.autoUpdate;", + " const levels = data.levels;", + " for (let l = 0; l < levels.length; l++) {", + " const level = levels[l];", + " const child = object.getObjectByProperty('uuid', level.object);", + " if (child !== undefined) {", + " object.addLevel(child, level.distance);", + " }", + " }", + " }", + " return object;", + " }", + "}", + "", + "const Plugins = [];", + "function loadPlugin(plugin) {", + " const existing = Plugins.find((item) => item.id === plugin.id);", + " if (!existing) {", + " plugin.initialize();", + " for (const emitterShape of plugin.emitterShapes) {", + " if (!EmitterShapes[emitterShape.type]) {", + " EmitterShapes[emitterShape.type] = emitterShape;", + " }", + " }", + " for (const behavior of plugin.behaviors) {", + " if (!BehaviorTypes[behavior.type]) {", + " BehaviorTypes[behavior.type] = behavior;", + " }", + " }", + " }", + "}", + "function unloadPlugin(pluginId) {", + " const plugin = Plugins.find((item) => item.id === pluginId);", + " if (plugin) {", + " for (const emitterShape of plugin.emitterShapes) {", + " if (EmitterShapes[emitterShape.type]) {", + " delete EmitterShapes[emitterShape.type];", + " }", + " }", + " for (const behavior of plugin.behaviors) {", + " if (BehaviorTypes[behavior.type]) {", + " delete BehaviorTypes[behavior.type];", + " }", + " }", + " }", + "}", + "", + "let NodeValueType = void 0;", + "(function (NodeValueType) {", + " NodeValueType[NodeValueType[\"Number\"] = 0] = \"Number\";", + " NodeValueType[NodeValueType[\"Vec2\"] = 1] = \"Vec2\";", + " NodeValueType[NodeValueType[\"Vec3\"] = 2] = \"Vec3\";", + " NodeValueType[NodeValueType[\"Vec4\"] = 3] = \"Vec4\";", + " NodeValueType[NodeValueType[\"Boolean\"] = 4] = \"Boolean\";", + " NodeValueType[NodeValueType[\"AnyType\"] = 5] = \"AnyType\";", + " NodeValueType[NodeValueType[\"NullableAnyType\"] = 6] = \"NullableAnyType\";", + " NodeValueType[NodeValueType[\"EventStream\"] = 7] = \"EventStream\";", + "})(NodeValueType || (NodeValueType = {}));", + "const genDefaultForNodeValueType = (type) => {", + " switch (type) {", + " case NodeValueType.Boolean:", + " return false;", + " case NodeValueType.Number:", + " return 0;", + " case NodeValueType.Vec2:", + " return new THREE.Vector2();", + " case NodeValueType.Vec3:", + " return new THREE.Vector3();", + " case NodeValueType.Vec4:", + " return new THREE.Vector4();", + " case NodeValueType.AnyType:", + " return 0;", + " case NodeValueType.NullableAnyType:", + " return undefined;", + " }", + "};", + "", + "class Node {", + " constructor(type, signatureIndex = -1, data = {}) {", + " this.inputs = [];", + " this.outputs = [];", + " this.signatureIndex = -1;", + " this.position = new THREE.Vector2();", + " this.outputValues = [];", + " this.id = '' + Math.round(Math.random() * 100000);", + " this.type = type;", + " this.signatureIndex = signatureIndex;", + " this.data = data;", + " const realIndex = signatureIndex === -1 ? 0 : signatureIndex;", + " for (let i = 0; i < type.nodeTypeSignatures[realIndex].inputTypes.length; i++) {", + " this.inputs.push(undefined);", + " }", + " for (let i = 0; i < type.nodeTypeSignatures[realIndex].outputTypes.length; i++) {", + " this.outputs.push([]);", + " this.outputValues.push(genDefaultForNodeValueType(type.nodeTypeSignatures[realIndex].outputTypes[i]));", + " }", + " }", + " get inputTypes() {", + " const signatureIndex = this.signatureIndex === -1 ? 0 : this.signatureIndex;", + " return this.type.nodeTypeSignatures[signatureIndex].inputTypes;", + " }", + " get outputTypes() {", + " const signatureIndex = this.signatureIndex === -1 ? 0 : this.signatureIndex;", + " return this.type.nodeTypeSignatures[signatureIndex].outputTypes;", + " }", + " func(context, inputs, outputs) {", + " const signatureIndex = this.signatureIndex === -1 ? 0 : this.signatureIndex;", + " this.type.nodeTypeSignatures[signatureIndex].func(context, this.data, inputs, outputs);", + " }", + "}", + "class Wire {", + " constructor(input, inputIndex, output, outputIndex) {", + " this.input = input;", + " this.inputIndex = inputIndex;", + " this.input.outputs[inputIndex].push(this);", + " this.output = output;", + " this.outputIndex = outputIndex;", + " this.output.inputs[outputIndex] = this;", + " }", + "}", + "", + "class BaseCompiler {", + " constructor() {", + " this.visited = new Set();", + " BaseCompiler.Instance = this;", + " }", + " buildExecutionOrder(graph, context) {", + " graph.nodesInOrder.length = 0;", + " this.visited.clear();", + " for (let i = 0; i < graph.outputNodes.length; i++) {", + " const node = graph.outputNodes[i];", + " if (node.inputs[0] !== undefined) {", + " this._traverse(node, graph, context);", + " }", + " }", + " graph.compiled = true;", + " }", + " _traverse(node, graph, context) {", + " this.visited.add(node.id);", + " for (let i = 0; i < node.inputs.length; i++) {", + " if (node.inputs[i] instanceof Wire) {", + " const inputNode = node.inputs[i].input;", + " if (!this.visited.has(inputNode.id)) {", + " this._traverse(inputNode, graph, context);", + " }", + " }", + " else if (node.inputs[i] !== undefined);", + " else;", + " }", + " graph.nodesInOrder.push(node);", + " }", + "}", + "", + "class Interpreter extends BaseCompiler {", + " constructor() {", + " super();", + " }", + " executeCompiledGraph(graph, context) {", + " const nodes = graph.nodesInOrder;", + " for (let i = 0; i < nodes.length; i++) {", + " const inputValues = [];", + " const node = nodes[i];", + " for (let j = 0; j < node.inputs.length; j++) {", + " if (node.inputs[j] instanceof Wire) {", + " inputValues.push(node.inputs[j].input.outputValues[node.inputs[j].inputIndex]);", + " }", + " else if (node.inputs[j] !== undefined) {", + " inputValues.push(node.inputs[j].getValue(context));", + " }", + " else {", + " inputValues.push(undefined);", + " }", + " }", + " node.func(context, inputValues, node.outputValues);", + " }", + " }", + " run(graph, context) {", + " if (!graph.compiled) {", + " this.buildExecutionOrder(graph, context);", + " }", + " this.executeCompiledGraph(graph, context);", + " }", + "}", + "", + "class NodeType {", + " constructor(name) {", + " this.nodeTypeSignatures = [];", + " this.name = name;", + " }", + " addSignature(inputTypes, outputTypes, func) {", + " this.nodeTypeSignatures.push({", + " inputTypes: inputTypes,", + " outputTypes: outputTypes,", + " func: func,", + " });", + " }", + "}", + "class GraphNodeType extends NodeType {", + " constructor(nodeGraph) {", + " const inputTypes = [];", + " for (let i = 0; i < nodeGraph.inputNodes.length; i++) {", + " if (nodeGraph.inputNodes[i].type.name === 'input') {", + " inputTypes.push(nodeGraph.inputNodes[i].data.type);", + " }", + " }", + " const outputTypes = [];", + " for (let i = 0; i < nodeGraph.outputNodes.length; i++) {", + " if (nodeGraph.outputNodes[i].type.name === 'output') {", + " outputTypes.push(nodeGraph.outputNodes[i].data.type);", + " }", + " }", + " super(nodeGraph.name);", + " this.addSignature(inputTypes, outputTypes, (context, data, inputs, outputs) => {", + " context.inputs = inputs;", + " context.outputs = outputs;", + " Interpreter.Instance.run(nodeGraph, context);", + " });", + " this.nodeGraph = nodeGraph;", + " }", + "}", + "", + "const NodeTypes = {};", + "const addNode = new NodeType('add');", + "addNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] + inputs[1];", + "});", + "addNode.addSignature([NodeValueType.Vec2, NodeValueType.Vec2], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " outputs[0].addVectors(inputs[0], inputs[1]);", + "});", + "addNode.addSignature([NodeValueType.Vec3, NodeValueType.Vec3], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0].addVectors(inputs[0], inputs[1]);", + "});", + "addNode.addSignature([NodeValueType.Vec4, NodeValueType.Vec4], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " outputs[0].addVectors(inputs[0], inputs[1]);", + "});", + "NodeTypes['add'] = addNode;", + "const subNode = new NodeType('sub');", + "subNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] - inputs[1];", + "});", + "subNode.addSignature([NodeValueType.Vec2, NodeValueType.Vec2], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " outputs[0].subVectors(inputs[0], inputs[1]);", + "});", + "subNode.addSignature([NodeValueType.Vec3, NodeValueType.Vec3], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0].subVectors(inputs[0], inputs[1]);", + "});", + "subNode.addSignature([NodeValueType.Vec4, NodeValueType.Vec4], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " outputs[0].subVectors(inputs[0], inputs[1]);", + "});", + "NodeTypes['sub'] = subNode;", + "const mulNode = new NodeType('mul');", + "mulNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] * inputs[1];", + "});", + "mulNode.addSignature([NodeValueType.Vec2, NodeValueType.Number], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).multiplyScalar(inputs[1]);", + "});", + "mulNode.addSignature([NodeValueType.Vec3, NodeValueType.Number], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).multiplyScalar(inputs[1]);", + "});", + "mulNode.addSignature([NodeValueType.Vec4, NodeValueType.Number], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).multiplyScalar(inputs[1]);", + "});", + "NodeTypes['mul'] = mulNode;", + "const divNode = new NodeType('div');", + "divNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] / inputs[1];", + "});", + "divNode.addSignature([NodeValueType.Vec2, NodeValueType.Number], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).divideScalar(inputs[1]);", + "});", + "divNode.addSignature([NodeValueType.Vec3, NodeValueType.Number], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).divideScalar(inputs[1]);", + "});", + "divNode.addSignature([NodeValueType.Vec4, NodeValueType.Number], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).divideScalar(inputs[1]);", + "});", + "NodeTypes['div'] = divNode;", + "const sinNode = new NodeType('sin');", + "sinNode.addSignature([NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = Math.sin(inputs[0]);", + "});", + "NodeTypes['sin'] = sinNode;", + "const cosNode = new NodeType('cos');", + "cosNode.addSignature([NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = Math.cos(inputs[0]);", + "});", + "NodeTypes['cos'] = cosNode;", + "const tanNode = new NodeType('tan');", + "tanNode.addSignature([NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = Math.tan(inputs[0]);", + "});", + "NodeTypes['tan'] = tanNode;", + "const absNode = new NodeType('abs');", + "absNode.addSignature([NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = Math.abs(inputs[0]);", + "});", + "NodeTypes['abs'] = absNode;", + "const minNode = new NodeType('min');", + "minNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = Math.min(inputs[0], inputs[1]);", + "});", + "NodeTypes['min'] = minNode;", + "const maxNode = new NodeType('max');", + "maxNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = Math.max(inputs[0], inputs[1]);", + "});", + "NodeTypes['max'] = maxNode;", + "const dot = new NodeType('dot');", + "dot.addSignature([NodeValueType.Vec2, NodeValueType.Vec2], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].dot(inputs[1]);", + "});", + "dot.addSignature([NodeValueType.Vec3, NodeValueType.Vec3], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].dot(inputs[1]);", + "});", + "dot.addSignature([NodeValueType.Vec4, NodeValueType.Vec4], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].dot(inputs[1]);", + "});", + "NodeTypes['dot'] = dot;", + "const cross = new NodeType('cross');", + "cross.addSignature([NodeValueType.Vec3, NodeValueType.Vec3], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0].crossVectors(inputs[0], inputs[1]);", + "});", + "NodeTypes['cross'] = cross;", + "const length = new NodeType('length');", + "length.addSignature([NodeValueType.Vec2], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].length();", + "});", + "length.addSignature([NodeValueType.Vec3], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].length();", + "});", + "length.addSignature([NodeValueType.Vec4], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].length();", + "});", + "NodeTypes['length'] = length;", + "const lengthSq = new NodeType('lengthSq');", + "lengthSq.addSignature([NodeValueType.Vec2], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].lengthSq();", + "});", + "lengthSq.addSignature([NodeValueType.Vec3], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].lengthSq();", + "});", + "lengthSq.addSignature([NodeValueType.Vec4], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].lengthSq();", + "});", + "NodeTypes['lengthSq'] = lengthSq;", + "const normalize = new NodeType('normalize');", + "normalize.addSignature([NodeValueType.Vec2], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).normalize();", + "});", + "normalize.addSignature([NodeValueType.Vec3], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).normalize();", + "});", + "normalize.addSignature([NodeValueType.Vec4], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " outputs[0].copy(inputs[0]).normalize();", + "});", + "NodeTypes['normalize'] = normalize;", + "const distance = new NodeType('distance');", + "distance.addSignature([NodeValueType.Vec2, NodeValueType.Vec2], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].distanceTo(inputs[1]);", + "});", + "distance.addSignature([NodeValueType.Vec3, NodeValueType.Vec3], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].distanceTo(inputs[1]);", + "});", + "NodeTypes['distance'] = distance;", + "const andNode = new NodeType('and');", + "andNode.addSignature([NodeValueType.Boolean, NodeValueType.Boolean], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] && inputs[1];", + "});", + "NodeTypes['and'] = andNode;", + "const orNode = new NodeType('or');", + "orNode.addSignature([NodeValueType.Boolean, NodeValueType.Boolean], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] || inputs[1];", + "});", + "NodeTypes['or'] = orNode;", + "const notNode = new NodeType('not');", + "notNode.addSignature([NodeValueType.Boolean], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = !inputs[0];", + "});", + "NodeTypes['not'] = notNode;", + "const equalNode = new NodeType('equal');", + "equalNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] === inputs[1];", + "});", + "equalNode.addSignature([NodeValueType.Vec2, NodeValueType.Vec2], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].equals(inputs[1]);", + "});", + "equalNode.addSignature([NodeValueType.Vec3, NodeValueType.Vec3], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].equals(inputs[1]);", + "});", + "equalNode.addSignature([NodeValueType.Vec4, NodeValueType.Vec4], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].equals(inputs[1]);", + "});", + "NodeTypes['equal'] = equalNode;", + "const lessThanNode = new NodeType('lessThan');", + "lessThanNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] < inputs[1];", + "});", + "NodeTypes['lessThan'] = lessThanNode;", + "const greaterThanNode = new NodeType('greaterThan');", + "greaterThanNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] > inputs[1];", + "});", + "NodeTypes['greaterThan'] = greaterThanNode;", + "const lessThanOrEqualNode = new NodeType('lessThanOrEqual');", + "lessThanOrEqualNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] <= inputs[1];", + "});", + "NodeTypes['lessThanOrEqual'] = lessThanOrEqualNode;", + "const greaterThanOrEqualNode = new NodeType('greaterThanOrEqual');", + "greaterThanOrEqualNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] >= inputs[1];", + "});", + "NodeTypes['greaterThanOrEqual'] = greaterThanOrEqualNode;", + "const ifNode = new NodeType('if');", + "ifNode.addSignature([NodeValueType.Boolean, NodeValueType.AnyType, NodeValueType.AnyType], [NodeValueType.AnyType], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0] ? inputs[1] : inputs[2];", + "});", + "NodeTypes['if'] = ifNode;", + "const numberNode = new NodeType('number');", + "numberNode.addSignature([], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = data.value;", + "});", + "NodeTypes['number'] = numberNode;", + "const vec2Node = new NodeType('vec2');", + "vec2Node.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " outputs[0].x = inputs[0];", + " outputs[0].y = inputs[1];", + "});", + "NodeTypes['vec2'] = vec2Node;", + "const vec3Node = new NodeType('vec3');", + "vec3Node.addSignature([NodeValueType.Number, NodeValueType.Number, NodeValueType.Number], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0].x = inputs[0];", + " outputs[0].y = inputs[1];", + " outputs[0].z = inputs[2];", + "});", + "NodeTypes['vec3'] = vec3Node;", + "const vec4Node = new NodeType('vec4');", + "vec4Node.addSignature([NodeValueType.Number, NodeValueType.Number, NodeValueType.Number, NodeValueType.Number], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " outputs[0].x = inputs[0];", + " outputs[0].y = inputs[1];", + " outputs[0].z = inputs[2];", + " outputs[0].w = inputs[3];", + "});", + "NodeTypes['vec4'] = vec4Node;", + "const splitVec2Node = new NodeType('splitVec2');", + "splitVec2Node.addSignature([NodeValueType.Vec2], [NodeValueType.Number, NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].x;", + " outputs[1] = inputs[0].y;", + "});", + "NodeTypes['splitVec2'] = splitVec2Node;", + "const splitVec3Node = new NodeType('splitVec3');", + "splitVec3Node.addSignature([NodeValueType.Vec3], [NodeValueType.Number, NodeValueType.Number, NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].x;", + " outputs[1] = inputs[0].y;", + " outputs[2] = inputs[0].z;", + "});", + "NodeTypes['splitVec3'] = splitVec3Node;", + "const splitVec4Node = new NodeType('splitVec4');", + "splitVec4Node.addSignature([NodeValueType.Vec4], [NodeValueType.Number, NodeValueType.Number, NodeValueType.Number, NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0].x;", + " outputs[1] = inputs[0].y;", + " outputs[2] = inputs[0].z;", + " outputs[3] = inputs[0].w;", + "});", + "NodeTypes['splitVec4'] = splitVec4Node;", + "const boolNode = new NodeType('bool');", + "boolNode.addSignature([], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = data.value;", + "});", + "NodeTypes['bool'] = boolNode;", + "const particlePropertyNode = new NodeType('particleProperty');", + "particlePropertyNode.addSignature([NodeValueType.NullableAnyType], [NodeValueType.NullableAnyType], (context, data, inputs, outputs) => {", + " if (inputs[0] !== undefined) {", + " if (typeof inputs[0] === 'object') {", + " context.particle[data.property].copy(inputs[0]);", + " }", + " else {", + " context.particle[data.property] = inputs[0];", + " }", + " }", + " if (context.particle[data.property] !== undefined) {", + " if (typeof outputs[0] === 'object') {", + " outputs[0].copy(context.particle[data.property]);", + " }", + " else {", + " outputs[0] = context.particle[data.property];", + " }", + " }", + "});", + "NodeTypes['particleProperty'] = particlePropertyNode;", + "const emitNode = new NodeType('emit');", + "emitNode.addSignature([NodeValueType.EventStream], [], (context, data, inputs, outputs) => {", + " const arr = inputs[0];", + " for (let i = 0; i < arr.length; i++) {", + " context.signal(i, arr[i]);", + " }", + "});", + "NodeTypes['emit'] = emitNode;", + "const graphPropertyNode = new NodeType('graphProperty');", + "graphPropertyNode.addSignature([NodeValueType.NullableAnyType], [NodeValueType.NullableAnyType], (context, data, inputs, outputs) => {", + " if (inputs[0] !== undefined) {", + " if (typeof inputs[0] === 'object') {", + " context.graph[data.property].copy(inputs[0]);", + " }", + " else {", + " context.graph[data.property] = inputs[0];", + " }", + " }", + " if (context.graph[data.property] !== undefined) {", + " if (typeof outputs[0] === 'object') {", + " outputs[0].copy(context.graph[data.property]);", + " }", + " else {", + " outputs[0] = context.graph[data.property];", + " }", + " }", + "});", + "NodeTypes['graphProperty'] = graphPropertyNode;", + "const startEventNode = new NodeType('startEvent');", + "startEventNode.addSignature([], [NodeValueType.EventStream], (context, data, inputs, outputs) => {", + " outputs[0] = [{ type: 'start' }];", + "});", + "NodeTypes['startEvent'] = startEventNode;", + "const repeaterNode = new NodeType('repeater');", + "repeaterNode.addSignature([NodeValueType.EventStream, NodeValueType.Number], [NodeValueType.EventStream], (context, data, inputs, outputs) => {", + " const arr = inputs[0];", + " const count = inputs[1];", + " const result = [];", + " for (let j = 0; j < arr.length; j++) {", + " for (let i = 0; i < count; i++) {", + " result.push(arr[j]);", + " }", + " }", + " outputs[0] = result;", + "});", + "NodeTypes['repeater'] = repeaterNode;", + "const timeNode = new NodeType('time');", + "timeNode.addSignature([], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = context.emissionState.time;", + "});", + "NodeTypes['time'] = timeNode;", + "const deltaNode = new NodeType('delta');", + "deltaNode.addSignature([], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = context.delta;", + "});", + "NodeTypes['delta'] = deltaNode;", + "const outputNode = new NodeType('output');", + "outputNode.addSignature([NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0];", + "});", + "outputNode.addSignature([NodeValueType.Vec2], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0];", + "});", + "outputNode.addSignature([NodeValueType.Vec3], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0];", + "});", + "outputNode.addSignature([NodeValueType.Vec4], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0];", + "});", + "outputNode.addSignature([NodeValueType.Boolean], [NodeValueType.Boolean], (context, data, inputs, outputs) => {", + " outputs[0] = inputs[0];", + "});", + "NodeTypes['output'] = outputNode;", + "const lerpNode = new NodeType('lerp');", + "lerpNode.addSignature([NodeValueType.Number, NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] =", + " inputs[0] * (1 - inputs[2]) + inputs[1] * inputs[2];", + "});", + "lerpNode.addSignature([NodeValueType.Vec2, NodeValueType.Vec2, NodeValueType.Number], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " outputs[0].lerpVectors(inputs[0], inputs[1], inputs[2]);", + "});", + "lerpNode.addSignature([NodeValueType.Vec3, NodeValueType.Vec3, NodeValueType.Number], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " outputs[0].lerpVectors(inputs[0], inputs[1], inputs[2]);", + "});", + "lerpNode.addSignature([NodeValueType.Vec4, NodeValueType.Vec4, NodeValueType.Number], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " outputs[0].lerpVectors(inputs[0], inputs[1], inputs[2]);", + "});", + "NodeTypes['lerp'] = lerpNode;", + "const normalD = (x) => {", + " return (1 / Math.sqrt(2 * Math.PI)) * Math.exp(x * x * -0.5);", + "};", + "const normalDistributionNode = new NodeType('normDistrib');", + "normalDistributionNode.addSignature([NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = normalD(inputs[0]);", + "});", + "NodeTypes['normDistrib'] = normalDistributionNode;", + "const normcdfNode = new NodeType('normcdf');", + "normcdfNode.addSignature([NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " let x = inputs[0];", + " const a1 = 0.254829592;", + " const a2 = -0.284496736;", + " const a3 = 1.421413741;", + " const a4 = -1.453152027;", + " const a5 = 1.061405429;", + " const p = 0.3275911;", + " let sign = 1;", + " if (x < 0)", + " sign = -1;", + " x = Math.abs(x) / Math.sqrt(2.0);", + " const t = 1.0 / (1.0 + p * x);", + " const y = 1.0 - ((((a5 * t + a4) * t + a3) * t + a2) * t + a1) * t * Math.exp(-x * x);", + " outputs[0] = 0.5 * (1.0 + sign * y);", + "});", + "NodeTypes['normcdf'] = normcdfNode;", + "const normcdfInvNode = new NodeType('normcdfInv');", + "const rationalApproximation = (t) => {", + " const c = [2.515517, 0.802853, 0.010328];", + " const d = [1.432788, 0.189269, 0.001308];", + " return t - ((c[2] * t + c[1]) * t + c[0]) / (((d[2] * t + d[1]) * t + d[0]) * t + 1.0);", + "};", + "const normcdfInv = (p) => {", + " if (p < 0.5) {", + " return -rationalApproximation(Math.sqrt(-2.0 * Math.log(p)));", + " }", + " else {", + " return rationalApproximation(Math.sqrt(-2.0 * Math.log(1 - p)));", + " }", + "};", + "normcdfInvNode.addSignature([NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = normcdfInv(inputs[0]);", + "});", + "NodeTypes['normcdfInv'] = normcdfInvNode;", + "const clampNode = new NodeType('clamp');", + "clampNode.addSignature([NodeValueType.Number, NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = Math.max(Math.min(inputs[0], inputs[2]), inputs[1]);", + "});", + "NodeTypes['clamp'] = clampNode;", + "const smoothstepNode = new NodeType('smoothstep');", + "smoothstepNode.addSignature([NodeValueType.Number, NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " const x = Math.max(Math.min(inputs[0], inputs[2]), inputs[1]);", + " outputs[0] = x * x * (3 - 2 * x);", + "});", + "NodeTypes['smoothstep'] = smoothstepNode;", + "const randomNode = new NodeType('random');", + "randomNode.addSignature([NodeValueType.Number, NodeValueType.Number], [NodeValueType.Number], (context, data, inputs, outputs) => {", + " outputs[0] = Math.random() * (inputs[1] - inputs[0]) + inputs[0];", + "});", + "randomNode.addSignature([NodeValueType.Vec2, NodeValueType.Vec2], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " let random = Math.random();", + " outputs[0].lerpVectors(inputs[0], inputs[1], random);", + "});", + "randomNode.addSignature([NodeValueType.Vec3, NodeValueType.Vec3], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " let random = Math.random();", + " outputs[0].lerpVectors(inputs[0], inputs[1], random);", + "});", + "randomNode.addSignature([NodeValueType.Vec4, NodeValueType.Vec4], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " let random = Math.random();", + " outputs[0].lerpVectors(inputs[0], inputs[1], random);", + "});", + "NodeTypes['random'] = randomNode;", + "const vrandNode = new NodeType('vrand');", + "vrandNode.addSignature([], [NodeValueType.Vec2], (context, data, inputs, outputs) => {", + " let x = normcdfInv(Math.random());", + " let y = normcdfInv(Math.random());", + " const mag = Math.sqrt(x * x + y * y);", + " outputs[0].set(x / mag, y / mag);", + "});", + "vrandNode.addSignature([], [NodeValueType.Vec3], (context, data, inputs, outputs) => {", + " let x = normcdfInv(Math.random());", + " let y = normcdfInv(Math.random());", + " let z = normcdfInv(Math.random());", + " const mag = Math.sqrt(x * x + y * y + z * z);", + " outputs[0].set(x / mag, y / mag, z / mag);", + "});", + "vrandNode.addSignature([], [NodeValueType.Vec4], (context, data, inputs, outputs) => {", + " let x = normcdfInv(Math.random());", + " let y = normcdfInv(Math.random());", + " let z = normcdfInv(Math.random());", + " let w = normcdfInv(Math.random());", + " const mag = Math.sqrt(x * x + y * y + z * z + w * w);", + " outputs[0].set(x / mag, y / mag, z / mag, w / mag);", + "});", + "NodeTypes['vrand'] = vrandNode;", + "const bsdfNode = new NodeType('bsdf');", + "bsdfNode.addSignature([NodeValueType.Vec3, NodeValueType.Vec3, NodeValueType.Vec3, NodeValueType.Number], [], (context, data, inputs, outputs) => { });", + "NodeTypes['bsdf'] = bsdfNode;", + "const OutputNodeTypeNames = new Set(['output', 'particleProperty', 'graphProperty', 'emit']);", + "", + "class NodeGraph {", + " constructor(name) {", + " this.inputNodes = [];", + " this.outputNodes = [];", + " this.allNodes = new Map();", + " this.wires = [];", + " this.compiled = false;", + " this.nodesInOrder = [];", + " this.version = '1.0';", + " this.uuid = THREE.MathUtils.generateUUID();", + " this.name = name;", + " this.revision = 0;", + " }", + " addWire(wire) {", + " this.wires.push(wire);", + " this.revision++;", + " }", + " addNode(node) {", + " this.allNodes.set(node.id, node);", + " if (node.type === NodeTypes['input']) {", + " this.inputNodes.push(node);", + " }", + " else if (OutputNodeTypeNames.has(node.type.name)) {", + " this.outputNodes.push(node);", + " }", + " this.revision++;", + " }", + " getNode(id) {", + " return this.allNodes.get(id);", + " }", + " deleteNode(node) {", + " this.allNodes.delete(node.id);", + " this.revision++;", + " }", + " deleteWire(wire) {", + " let index = wire.input.outputs[wire.inputIndex].indexOf(wire);", + " if (index !== -1) {", + " wire.input.outputs[wire.inputIndex].splice(index, 1);", + " }", + " wire.output.inputs[wire.outputIndex] = undefined;", + " index = this.wires.indexOf(wire);", + " if (index != -1) {", + " this.wires[index] = this.wires[this.wires.length - 1];", + " this.wires.pop();", + " }", + " this.revision++;", + " }", + " toJSON() {", + " throw new Error('not implemented');", + " }", + " clone() {", + " throw new Error('not implemented');", + " }", + "}", + "", + "new THREE.Vector3(0, 0, 1);", + "const tempQ = new THREE.Quaternion();", + "const tempV = new THREE.Vector3();", + "const tempV2 = new THREE.Vector3();", + "const PREWARM_FPS = 60;", + "const DEFAULT_GEOMETRY = new THREE.PlaneGeometry(1, 1, 1, 1);", + "class NodeVFX {", + " set time(time) {", + " this.emissionState.time = time;", + " }", + " get time() {", + " return this.emissionState.time;", + " }", + " get layers() {", + " return this.rendererSettings.layers;", + " }", + " get texture() {", + " return this.rendererSettings.material.map;", + " }", + " set texture(texture) {", + " this.rendererSettings.material.map = texture;", + " this.neededToUpdateRender = true;", + " }", + " get material() {", + " return this.rendererSettings.material;", + " }", + " set material(material) {", + " this.rendererSettings.material = material;", + " this.neededToUpdateRender = true;", + " }", + " get instancingGeometry() {", + " return this.rendererSettings.instancingGeometry;", + " }", + " set instancingGeometry(geometry) {", + " this.restart();", + " this.particles.length = 0;", + " this.rendererSettings.instancingGeometry = geometry;", + " this.neededToUpdateRender = true;", + " }", + " get renderMode() {", + " return this.rendererSettings.renderMode;", + " }", + " set renderMode(renderMode) {", + " if ((this.rendererSettings.renderMode != RenderMode.Trail && renderMode === RenderMode.Trail) ||", + " (this.rendererSettings.renderMode == RenderMode.Trail && renderMode !== RenderMode.Trail)) {", + " this.restart();", + " this.particles.length = 0;", + " }", + " if (this.rendererSettings.renderMode !== renderMode) {", + " switch (renderMode) {", + " case RenderMode.Trail:", + " this.rendererEmitterSettings = {", + " startLength: 30,", + " followLocalOrigin: false,", + " };", + " break;", + " case RenderMode.Mesh:", + " this.rendererEmitterSettings = {", + " geometry: new THREE.PlaneGeometry(1, 1),", + " };", + " break;", + " case RenderMode.BillBoard:", + " case RenderMode.VerticalBillBoard:", + " case RenderMode.HorizontalBillBoard:", + " case RenderMode.StretchedBillBoard:", + " this.rendererEmitterSettings = {};", + " break;", + " }", + " }", + " this.rendererSettings.renderMode = renderMode;", + " this.neededToUpdateRender = true;", + " }", + " get renderOrder() {", + " return this.rendererSettings.renderOrder;", + " }", + " set renderOrder(renderOrder) {", + " this.rendererSettings.renderOrder = renderOrder;", + " this.neededToUpdateRender = true;", + " }", + " get blending() {", + " return this.rendererSettings.material.blending;", + " }", + " set blending(blending) {", + " this.rendererSettings.material.blending = blending;", + " this.neededToUpdateRender = true;", + " }", + " constructor(parameters) {", + " var _a, _b, _c, _d, _e, _f, _g;", + " this.temp = new THREE.Vector3();", + " this.travelDistance = 0;", + " this.normalMatrix = new THREE.Matrix3();", + " this.speedFactor = 0;", + " this.autoDestroy = parameters.autoDestroy === undefined ? false : parameters.autoDestroy;", + " this.duration = (_a = parameters.duration) !== null && _a !== void 0 ? _a : 1;", + " this.looping = parameters.looping === undefined ? true : parameters.looping;", + " this.prewarm = parameters.prewarm === undefined ? false : parameters.prewarm;", + " this.worldSpace = (_b = parameters.worldSpace) !== null && _b !== void 0 ? _b : false;", + " this.rendererEmitterSettings = (_c = parameters.rendererEmitterSettings) !== null && _c !== void 0 ? _c : {};", + " this.emissionGraph = parameters.emissionGraph;", + " this.updateGraph = parameters.updateGraph;", + " this.interpreter = new Interpreter();", + " this.rendererSettings = {", + " instancingGeometry: (_d = parameters.instancingGeometry) !== null && _d !== void 0 ? _d : DEFAULT_GEOMETRY,", + " renderMode: (_e = parameters.renderMode) !== null && _e !== void 0 ? _e : RenderMode.BillBoard,", + " renderOrder: (_f = parameters.renderOrder) !== null && _f !== void 0 ? _f : 0,", + " material: parameters.material,", + " layers: (_g = parameters.layers) !== null && _g !== void 0 ? _g : new THREE.Layers(),", + " uTileCount: 1,", + " vTileCount: 1,", + " };", + " this.neededToUpdateRender = true;", + " this.particles = new Array();", + " this.emitter = new ParticleEmitter(this);", + " this.paused = false;", + " this.particleNum = 0;", + " this.emissionState = {", + " time: 0,", + " };", + " this.emitEnded = false;", + " this.markForDestroy = false;", + " this.prewarmed = false;", + " }", + " pause() {", + " this.paused = true;", + " }", + " play() {", + " this.paused = false;", + " }", + " spawn(emissionState, matrix) {", + " tempQ.setFromRotationMatrix(matrix);", + " const translation = tempV;", + " const quaternion = tempQ;", + " const scale = tempV2;", + " matrix.decompose(translation, quaternion, scale);", + " this.particleNum++;", + " while (this.particles.length < this.particleNum) {", + " this.particles.push(new NodeParticle());", + " }", + " const particle = this.particles[this.particleNum - 1];", + " particle.reset();", + " this.interpreter.run(this.updateGraph, { particle: particle, emissionState: this.emissionState });", + " if (this.rendererSettings.renderMode === RenderMode.Trail &&", + " this.rendererEmitterSettings.followLocalOrigin) {", + " const trail = particle;", + " trail.localPosition = new THREE.Vector3().copy(trail.position);", + " }", + " if (this.worldSpace) {", + " particle.position.applyMatrix4(matrix);", + " particle.size *= (Math.abs(scale.x) + Math.abs(scale.y) + Math.abs(scale.z)) / 3;", + " particle.velocity.multiply(scale).applyMatrix3(this.normalMatrix);", + " if (particle.rotation && particle.rotation instanceof THREE.Quaternion) {", + " particle.rotation.multiplyQuaternions(tempQ, particle.rotation);", + " }", + " }", + " }", + " endEmit() {", + " this.emitEnded = true;", + " if (this.autoDestroy) {", + " this.markForDestroy = true;", + " }", + " }", + " dispose() {", + " if (this._renderer)", + " this._renderer.deleteSystem(this);", + " this.emitter.dispose();", + " if (this.emitter.parent)", + " this.emitter.parent.remove(this.emitter);", + " }", + " restart() {", + " this.paused = false;", + " this.particleNum = 0;", + " this.emissionState.time = 0;", + " this.emitEnded = false;", + " this.markForDestroy = false;", + " this.prewarmed = false;", + " }", + " update(delta) {", + " if (this.paused)", + " return;", + " let currentParent = this.emitter;", + " while (currentParent.parent) {", + " currentParent = currentParent.parent;", + " }", + " if (currentParent.type !== 'Scene') {", + " this.dispose();", + " return;", + " }", + " if (this.emitEnded && this.particleNum === 0) {", + " if (this.markForDestroy && this.emitter.parent)", + " this.dispose();", + " return;", + " }", + " if (this.looping && this.prewarm && !this.prewarmed) {", + " this.prewarmed = true;", + " for (let i = 0; i < this.duration * PREWARM_FPS; i++) {", + " this.update(1.0 / PREWARM_FPS);", + " }", + " }", + " if (delta > 0.1) {", + " delta = 0.1;", + " }", + " if (this.neededToUpdateRender) {", + " if (this._renderer)", + " this._renderer.updateSystem(this);", + " this.neededToUpdateRender = false;", + " }", + " this.emit(delta, this.emissionState, this.emitter.matrixWorld);", + " const context = { particle: undefined, emissionState: this.emissionState, delta };", + " for (let i = 0; i < this.particleNum; i++) {", + " context.particle = this.particles[i];", + " this.interpreter.run(this.updateGraph, context);", + " }", + " for (let i = 0; i < this.particleNum; i++) {", + " if (this.rendererEmitterSettings.followLocalOrigin &&", + " this.particles[i].localPosition) {", + " this.particles[i].position.copy(this.particles[i].localPosition);", + " if (this.particles[i].parentMatrix) {", + " this.particles[i].position.applyMatrix4(this.particles[i].parentMatrix);", + " }", + " else {", + " this.particles[i].position.applyMatrix4(this.emitter.matrixWorld);", + " }", + " }", + " else {", + " this.particles[i].position.addScaledVector(this.particles[i].velocity, delta);", + " }", + " this.particles[i].age += delta;", + " }", + " if (this.rendererSettings.renderMode === RenderMode.Trail) {", + " for (let i = 0; i < this.particleNum; i++) {", + " const particle = this.particles[i];", + " particle.update();", + " }", + " }", + " for (let i = 0; i < this.particleNum; i++) {", + " const particle = this.particles[i];", + " if (particle.died && (!(particle instanceof TrailParticle) || particle.previous.length === 0)) {", + " this.particles[i] = this.particles[this.particleNum - 1];", + " this.particles[this.particleNum - 1] = particle;", + " this.particleNum--;", + " i--;", + " }", + " }", + " }", + " emit(delta, emissionState, emitterMatrix) {", + " if (emissionState.time > this.duration) {", + " if (this.looping) {", + " emissionState.time -= this.duration;", + " }", + " else {", + " if (!this.emitEnded) {", + " this.endEmit();", + " }", + " }", + " }", + " this.normalMatrix.getNormalMatrix(emitterMatrix);", + " const context = {", + " signal: () => {", + " this.spawn(emissionState, emitterMatrix);", + " },", + " emissionState,", + " delta,", + " };", + " if (!this.emitEnded) {", + " this.interpreter.run(this.emissionGraph, context);", + " }", + " if (this.previousWorldPos === undefined)", + " this.previousWorldPos = new THREE.Vector3();", + " this.emitter.getWorldPosition(this.previousWorldPos);", + " emissionState.time += delta;", + " }", + " toJSON(meta, options = {}) {", + " return {};", + " }", + " getRendererSettings() {", + " return this.rendererSettings;", + " }", + " clone() {", + " return this;", + " }", + "}", + "", + "gdjs.__particleEmmiter3DExtension = {", + " ParticleEmitter3DRenderer,", + " ParticleEmitterAdapter,", + " ParticleEmitterHelper,", + "", + " ApplyCollision,", + " ApplyForce,", + " ApplySequences,", + " AxisAngleGenerator,", + " BatchedParticleRenderer,", + " BatchedRenderer,", + " BehaviorFromJSON,", + " BehaviorTypes,", + " Bezier,", + " ChangeEmitDirection,", + " ColorGeneratorFromJSON,", + " ColorOverLife,", + " ColorRange,", + " ConeEmitter,", + " ConstantColor,", + " ConstantValue,", + " DonutEmitter,", + " EmitSubParticleSystem,", + " EmitterFromJSON,", + " EmitterMode,", + " EmitterShapes,", + " EulerGenerator,", + " ForceOverLife,", + " FrameOverLife,", + " GeneratorFromJSON,", + " Gradient,", + " GraphNodeType,", + " GravityForce,", + " GridEmitter,", + " Interpreter,", + " IntervalValue,", + " MeshSurfaceEmitter,", + " Node,", + " NodeGraph,", + " NodeType,", + " NodeTypes,", + " NodeValueType,", + " Noise,", + " OrbitOverLife,", + " ParticleEmitter,", + " ParticleSystem,", + " PiecewiseBezier,", + " PiecewiseFunction,", + " Plugins,", + " PointEmitter,", + " QuarksLoader,", + " RandomColor,", + " RandomColorBetweenGradient,", + " RandomQuatGenerator,", + " RecordState,", + " RenderMode,", + " Rotation3DOverLife,", + " RotationGeneratorFromJSON,", + " RotationOverLife,", + " SequencerFromJSON,", + " SizeOverLife,", + " SpeedOverLife,", + " SphereEmitter,", + " SpriteBatch,", + " SpriteParticle,", + " SubParticleEmitMode,", + " TextureSequencer,", + " TrailBatch,", + " TrailParticle,", + " TurbulenceField,", + " VFXBatch,", + " ValueGeneratorFromJSON,", + " WidthOverLength,", + " Wire,", + " genDefaultForNodeValueType,", + " getPhysicsResolver,", + " loadPlugin,", + " setPhysicsResolver,", + " unloadPlugin,", + "}" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onScenePreEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "// See doStepPostEvents\r", + "runtimeScene.__particleEmmiter3DExtension = runtimeScene.__particleEmmiter3DExtension || {};\r", + "runtimeScene.__particleEmmiter3DExtension.emittersStepped = 0;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "DefineHelperClasses" + }, + { + "functionName": "onScenePreEvents" + } + ] + }, + "eventsBasedBehaviors": [], + "eventsBasedObjects": [ + { + "areaMaxX": 64, + "areaMaxY": 64, + "areaMaxZ": 64, + "areaMinX": 0, + "areaMinY": 0, + "areaMinZ": 0, + "defaultName": "ParticleEmitter", + "description": "Display a large number of particles to create visual effects.", + "fullName": "3D particle emitter", + "helpPath": "", + "iconUrl": "", + "is3D": true, + "isUsingLegacyInstancesRenderer": true, + "name": "ParticleEmitter3D", + "previewIconUrl": "", + "objects": [ + { + "adaptCollisionMaskAutomatically": true, + "assetStoreId": "", + "name": "Particle", + "type": "Sprite", + "updateIfNotVisible": false, + "variables": [], + "effects": [], + "behaviors": [], + "animations": [ + { + "name": "Image", + "useMultipleDirections": false, + "directions": [ + { + "looping": false, + "timeBetweenFrames": 0.08, + "sprites": [] + } + ] + } + ] + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Particle" + } + ] + }, + "objectsGroups": [], + "layers": [ + { + "ambientLightColorB": 200, + "ambientLightColorG": 200, + "ambientLightColorR": 200, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "", + "renderingType": "", + "visibility": true, + "cameras": [ + { + "defaultSize": true, + "defaultViewport": true, + "height": 0, + "viewportBottom": 1, + "viewportLeft": 0, + "viewportRight": 1, + "viewportTop": 0, + "width": 0 + } + ], + "effects": [] + } + ], + "instances": [], + "editionSettings": [], + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onCreated", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::DefineHelperClasses" + }, + "parameters": [ + "", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const {", + " ParticleEmitterAdapter,", + " ParticleEmitter3DRenderer,", + " ParticleEmitterHelper,", + "", + " ParticleSystem,", + " IntervalValue,", + " ConstantValue,", + " ConstantColor,", + " ColorOverLife,", + " SizeOverLife,", + " ApplyForce,", + " Gradient,", + " PiecewiseBezier,", + " Bezier,", + " PointEmitter,", + " ConeEmitter,", + " RenderMode", + "} = gdjs.__particleEmmiter3DExtension;", + "", + "/** @type {gdjs.CustomRuntimeObject} */", + "const object = objects[0];", + "// Force the size of the object because it doesn't contain any instance.", + "object._innerArea = {", + " min: [-16, -16, -16],", + " max: [16, 16, 16],", + " };", + "const hitbox = new gdjs.Polygon();", + "hitbox.vertices = [[-16, -16], [16, -16], [16, 16], [-16, 16]];", + "object._untransformedHitBoxes = [hitbox];", + "object._unrotatedAABB.min[0] = -16;", + "object._unrotatedAABB.min[1] = -16;", + "object._unrotatedAABB.max[0] = 16;", + "object._unrotatedAABB.max[1] = 16;", + "object._updateUntransformedHitBoxes = () => {};", + "", + "// Here runtimeScene is the gdjs.CustomRuntimeObjectInstanceContainer inside the custom object.", + "const gameScene = object.getRuntimeScene();", + "const game = runtimeScene.getGame();", + "", + "const texture = game.getImageManager().getThreeTexture('');", + "", + "// Set the blending here because changes are not applied after the emitter creation.", + "const blendingString = object._getBlending();", + "const blending =", + " blendingString === \"Additive\" ? THREE.AdditiveBlending :", + " blendingString === \"Normal\" ? THREE.NormalBlending :", + " blendingString === \"Subtractive\" ? THREE.SubtractiveBlending :", + " blendingString === \"Multiply\" ? THREE.MultiplyBlending :", + " blendingString === \"None\" ? THREE.NoBlending :", + " THREE.AdditiveBlending;", + "", + "", + "// Build a configuration with the right kind of objects.", + "// These values are not important as they are overrided by the object properties values.", + "const muzzle = {", + " duration: 10,", + " looping: false,", + " startLife: new IntervalValue(1, 2),", + " startSpeed: new IntervalValue(100, 200),", + " startSize: new IntervalValue(20, 50),", + " startColor: new ConstantColor(new THREE.Vector4(1, 1, 1, 1)),", + " worldSpace: true,", + "", + " maxParticle: 5,", + " emissionOverTime: new ConstantValue(50),", + " emissionBursts: [{", + " time: 0,", + " count: new ConstantValue(1),", + " cycle: 1,", + " interval: 0.01,", + " probability: 1,", + " }],", + "", + " shape: new PointEmitter(),", + " material: new THREE.MeshBasicMaterial({", + " map: texture,", + " blending: blending,", + " transparent: true,", + " side: THREE.DoubleSide", + " }),", + " startTileIndex: 0,", + " uTileCount: 1,", + " vTileCount: 1,", + " renderOrder: 2,", + " renderMode: RenderMode.BillBoard", + "};", + "const particleSystem = new ParticleSystem(muzzle);", + "", + "const colorOverLife = new ColorOverLife(", + " new Gradient(", + " [", + " [new THREE.Vector3(1, 0, 0), 0],", + " [new THREE.Vector3(1, 0, 0), 1],", + " ],", + " [", + " [1, 0],", + " [1, 1],", + " ]", + " ));", + "particleSystem.addBehavior(colorOverLife);", + "const sizeOverLife = new SizeOverLife(new PiecewiseBezier([[new Bezier(1, 2 / 3, 1 / 3, 0), 0]]));", + "particleSystem.addBehavior(sizeOverLife);", + "const applyForce = new ApplyForce(new THREE.Vector3(0, 0, -1), new ConstantValue(0));", + "particleSystem.addBehavior(applyForce);", + "", + "particleSystem.emitter.name = object.getName() + object.getNameId();", + "", + "object.__particleEmitterAdapter = new ParticleEmitterAdapter(particleSystem, colorOverLife, sizeOverLife, applyForce);", + "object.__particleSystem = particleSystem;", + "", + "// This is a hack that may break in future releases.", + "// Replace the group that would hold children objects by the emmiter.", + "const layer = object.getInstanceContainer().getLayer(object.getLayer());", + "const group = object.getRenderer()._threeGroup;", + "layer.getRenderer().remove3DRendererObject(group);", + "particleSystem.emitter.position.copy(group.position);", + "particleSystem.emitter.rotation.order = 'ZYX';", + "particleSystem.emitter.rotation.copy(group.rotation);", + "", + "const particleEmitter3DRenderer = new ParticleEmitter3DRenderer(object, object._instanceContainer, object.getInstanceContainer());", + "object._renderer = particleEmitter3DRenderer;", + "if (game.isInGameEdition && game.isInGameEdition()) {", + " const particleEmitterHelper = new ParticleEmitterHelper(object);", + " particleEmitter3DRenderer._threeGroup = particleEmitterHelper;", + " layer.getRenderer().add3DRendererObject(particleEmitterHelper);", + "}", + "else {", + " particleEmitter3DRenderer._threeGroup = particleSystem.emitter;", + " layer.getRenderer().add3DRendererObject(particleSystem.emitter);", + "}", + "", + "particleSystem.emitter.updateMatrixWorld(true);", + "", + "", + "// See doStepPostEvents", + "gameScene.__particleEmmiter3DExtension = gameScene.__particleEmmiter3DExtension || {};", + "gameScene.__particleEmmiter3DExtension.emittersCount = gameScene.__particleEmmiter3DExtension.emittersCount || 0;", + "gameScene.__particleEmmiter3DExtension.emittersCount++;", + "", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::UpdateFromProperties" + }, + "parameters": [ + "Object", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetRotationCenter" + }, + "parameters": [ + "Object", + "0", + "0", + "0" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onDestroy", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.CustomRuntimeObject} */", + "const object = objects[0];", + "// Here runtimeScene is the gdjs.CustomRuntimeObjectInstanceContainer inside the custom object.", + "const gameScene = object.getRuntimeScene();", + "", + "object.__particleSystem.dispose();", + "", + "// See doStepPostEvents", + "gameScene.__particleEmmiter3DExtension.emittersCount--;", + "", + "if (gameScene.__particleEmmiter3DExtension.emittersCount === 0) {", + " // Update batch system now because doStepPostEvents won't be called.", + " gameScene.__particleEmmiter3DExtension.layerNames = gameScene.__particleEmmiter3DExtension.layerNames || [];", + " const layerNames = gameScene.__particleEmmiter3DExtension.layerNames;", + " gameScene.getAllLayerNames(layerNames);", + " for (const layerName of layerNames) {", + " const layer = gameScene.getLayer(layerName);", + " if (layer.__particleEmmiter3DExtension) {", + " layer.__particleEmmiter3DExtension.batchSystem.update(layer.getElapsedTime() / 1000);", + " }", + " }", + "}" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onHotReloading", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::UpdateFromProperties" + }, + "parameters": [ + "Object", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Update from properties.", + "fullName": "Update from properties", + "functionType": "Action", + "name": "UpdateFromProperties", + "private": true, + "sentence": "Update from properties of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetZ" + }, + "parameters": [ + "Object", + "=", + "Object.Z()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetRotationX" + }, + "parameters": [ + "Object", + "=", + "Object.PropertyRotationX()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetRotationY" + }, + "parameters": [ + "Object", + "=", + "Object.PropertyRotationY()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetStartColor" + }, + "parameters": [ + "Object", + "=", + "Object.StartColor()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetEndColor" + }, + "parameters": [ + "Object", + "=", + "Object.EndColor()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetStartOpacity" + }, + "parameters": [ + "Object", + "=", + "Object.StartOpacity()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetEndOpacity" + }, + "parameters": [ + "Object", + "=", + "Object.EndOpacity()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetFlow" + }, + "parameters": [ + "Object", + "=", + "Object.Flow()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetStartSizeMin" + }, + "parameters": [ + "Object", + "=", + "Object.StartSizeMin()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetStartSizeMax" + }, + "parameters": [ + "Object", + "=", + "Object.StartSizeMax()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetEndScale" + }, + "parameters": [ + "Object", + "=", + "Object.EndScale()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetStartSpeedMin" + }, + "parameters": [ + "Object", + "=", + "Object.StartSpeedMin()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetStartSpeedMax" + }, + "parameters": [ + "Object", + "=", + "Object.StartSpeedMax()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetLifespanMin" + }, + "parameters": [ + "Object", + "=", + "Object.LifespanMin()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetLifespanMax" + }, + "parameters": [ + "Object", + "=", + "Object.LifespanMax()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetDuration" + }, + "parameters": [ + "Object", + "=", + "Object.Duration()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetSpayConeAngle" + }, + "parameters": [ + "Object", + "=", + "Object.SpayConeAngle()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetGravity" + }, + "parameters": [ + "Object", + "=", + "Object.Gravity()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetGravityTop" + }, + "parameters": [ + "Object", + "=", + "Object.GravityTop()", + "" + ] + }, + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::UpdateImage" + }, + "parameters": [ + "Object", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanVariable" + }, + "parameters": [ + "AreParticlesRelative", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetAreParticlesRelative" + }, + "parameters": [ + "Object", + "no", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "AreParticlesRelative", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetAreParticlesRelative" + }, + "parameters": [ + "Object", + "yes", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "TODO: Blending can't be changed." + }, + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::SetBlending" + }, + "parameters": [ + "Object", + "=", + "Object.Blending()", + "" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::UpdateHelper" + }, + "parameters": [ + "Object", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "Update helper", + "functionType": "Action", + "name": "UpdateHelper", + "private": true, + "sentence": "Update graphical helper of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const game = runtimeScene.getGame();", + "if (game.isInGameEdition && game.isInGameEdition()) {", + " const particleEmitterHelper = objects[0].get3DRendererObject();", + " particleEmitterHelper.update();", + "}" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "Update particle image", + "functionType": "Action", + "name": "UpdateImage", + "private": true, + "sentence": "Update particle image of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.CustomRuntimeObject3D} */\r", + "const object = objects[0];\r", + "/** @type {SpriteObjectDataType} */\r", + "const particleSpriteData = object._instanceContainer._objects.get(\"Particle\");\r", + "/** @type {gdjs.SpriteAnimationData} */\r", + "const animation = particleSpriteData.animations[0];\r", + "const animationFrame = animation ? animation.directions[0].sprites[0] : null;\r", + "const resourceName = animationFrame ? animationFrame.image : '';\r", + "object.__particleEmitterAdapter.setImage(resourceName);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "doStepPostEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::HasEnded" + }, + "parameters": [ + "Object", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::Delete" + }, + "parameters": [ + "Object", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "ParticleEmitter3D::ParticleEmitter3D::HasEnded" + }, + "parameters": [ + "Object", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ParticleEmitter3D::ParticleEmitter3D::RegisterInLayer" + }, + "parameters": [ + "Object", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.CustomRuntimeObject3D} */", + "const object = objects[0];", + "// Here runtimeScene is the gdjs.CustomRuntimeObjectInstanceContainer inside the custom object.", + "const gameScene = object.getRuntimeScene();", + "", + "// Update batch system after having moved every emitter.", + "// See onScenePreEvents", + "gameScene.__particleEmmiter3DExtension.emittersStepped++;", + "if (gameScene.__particleEmmiter3DExtension.emittersStepped === gameScene.__particleEmmiter3DExtension.emittersCount) {", + " gameScene.__particleEmmiter3DExtension.layerNames = gameScene.__particleEmmiter3DExtension.layerNames || [];", + " const layerNames = gameScene.__particleEmmiter3DExtension.layerNames;", + " gameScene.getAllLayerNames(layerNames);", + " for (const layerName of layerNames) {", + " const layer = gameScene.getLayer(layerName);", + " if (layer.__particleEmmiter3DExtension) {", + " layer.__particleEmmiter3DExtension.batchSystem.update(layer.getElapsedTime() / 1000);", + " }", + " }", + "}" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "Register in layer", + "functionType": "Action", + "name": "RegisterInLayer", + "private": true, + "sentence": "Register _PARAM0_ in layer", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.CustomRuntimeObject} */", + "const object = objects[0];", + "", + "// TODO Handle layer changes?", + "if (object.__emitterLayerName === undefined) {", + " // Here runtimeScene is the gdjs.CustomRuntimeObjectInstanceContainer inside the custom object.", + " const gameScene = object.getRuntimeScene();", + "", + " let rootObject = object;", + " while (rootObject.getInstanceContainer().getOwner) {", + " rootObject = rootObject.getInstanceContainer().getOwner();", + " }", + "", + " const layer = gameScene.getLayer(rootObject.getLayer());", + " layer.__particleEmmiter3DExtension = layer.__particleEmmiter3DExtension || {};", + " if (!layer.__particleEmmiter3DExtension.batchSystem) {", + " const batchSystem = new gdjs.__particleEmmiter3DExtension.BatchedRenderer();", + " batchSystem.scale.y *= -1;", + " const threeScene = layer.getRenderer().getThreeScene();", + " if (threeScene) {", + " threeScene.add(batchSystem);", + " }", + " layer.__particleEmmiter3DExtension.batchSystem = batchSystem;", + " }", + " layer.__particleEmmiter3DExtension.batchSystem.addSystem(object.__particleSystem);", + " object.__emitterLayerName = layer.getName();", + "}" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Delete itself", + "fullName": "Delete itself", + "functionType": "Action", + "name": "Delete", + "private": true, + "sentence": "Delete _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "", + "object.deleteFromScene(object.getParent());", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check that emission has ended and no particle is alive anymore.", + "fullName": "Emission has ended", + "functionType": "Condition", + "name": "HasEnded", + "sentence": "Emission from _PARAM0_ has ended", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "\r", + "eventsFunctionContext.returnValue =\r", + " object._getShouldAutodestruct()\r", + " && object.__particleSystem.emitEnded\r", + " && object.__particleSystem.particleNum === 0;\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Restart particule emission from the beginning.", + "fullName": "Restart", + "functionType": "Action", + "name": "Restart", + "sentence": "Restart particule emission from _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.CustomRuntimeObject} */\r", + "const object = objects[0];\r", + "\r", + "object.__particleSystem.restart();\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the Z position of the emitter.", + "fullName": "Z elevaltion (deprecated)", + "functionType": "ExpressionAndCondition", + "group": "Position", + "name": "Z", + "private": true, + "sentence": "the Z position", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyZ()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Z", + "group": "Position", + "name": "SetZ", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Z", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the rotation on X axis of the emitter.", + "fullName": "Rotation on X axis (deprecated)", + "functionType": "ExpressionAndCondition", + "group": "Angle", + "name": "RotationX", + "private": true, + "sentence": "the rotation on X axis", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyRotationX()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "RotationX", + "group": "Angle", + "name": "SetRotationX", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "RotationX", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "\r", + "object.__particleSystem.emitter.rotation.x = eventsFunctionContext.getArgument(\"Value\") * Math.PI / 180;" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the rotation on Y axis of the emitter.", + "fullName": "Rotation on Y axis (deprecated)", + "functionType": "ExpressionAndCondition", + "group": "Angle", + "name": "RotationY", + "private": true, + "sentence": "the rotation on Y axis", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyRotationY()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "RotationY", + "group": "Angle", + "name": "SetRotationY", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "RotationY", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "\r", + "object.__particleSystem.emitter.rotation.y = (90 + eventsFunctionContext.getArgument(\"Value\")) * Math.PI / 180;" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the start color of the object.", + "fullName": "Start color", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter color configuration", + "name": "StartColor", + "sentence": "the start color", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnString" + }, + "parameters": [ + "Object.PropertyStartColor()" + ] + } + ] + } + ], + "expressionType": { + "type": "color" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "StartColor", + "group": "3D particle emitter color configuration", + "name": "SetStartColor", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "StartColor", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const startColor = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setStartColor(startColor);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the end color of the object.", + "fullName": "End color", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter color configuration", + "name": "EndColor", + "sentence": "the end color", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnString" + }, + "parameters": [ + "Object.PropertyEndColor()" + ] + } + ] + } + ], + "expressionType": { + "type": "color" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "EndColor", + "group": "3D particle emitter color configuration", + "name": "SetEndColor", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "EndColor", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const endColor = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setEndColor(endColor);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the start opacity of the object.", + "fullName": "Start opacity", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter color configuration", + "name": "StartOpacity", + "sentence": "the start opacity", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyStartOpacity()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "StartOpacity", + "group": "3D particle emitter color configuration", + "name": "SetStartOpacity", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "StartOpacity", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const startOpacity = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setStartOpacity(startOpacity);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the end opacity of the object.", + "fullName": "End opacity", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter color configuration", + "name": "EndOpacity", + "sentence": "the end opacity", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyEndOpacity()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "EndOpacity", + "group": "3D particle emitter color configuration", + "name": "SetEndOpacity", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "EndOpacity", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const endOpacity = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setEndOpacity(endOpacity);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the flow of particles of the object (particles per second).", + "fullName": "Flow of particles", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter configuration", + "name": "Flow", + "sentence": "the flow of particles", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyFlow()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Flow", + "group": "3D particle emitter configuration", + "name": "SetFlow", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Flow", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const flow = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setFlow(flow);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the start min size of the object.", + "fullName": "Start min size", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter configuration", + "name": "StartSizeMin", + "sentence": "the start min size", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyStartSizeMin()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "StartSizeMin", + "group": "3D particle emitter configuration", + "name": "SetStartSizeMin", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "StartSizeMin", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const startMinSize = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setStartMinSize(startMinSize);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the start max size of the object.", + "fullName": "Start max size", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter configuration", + "name": "StartSizeMax", + "sentence": "the start max size", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyStartSizeMax()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "StartSizeMax", + "group": "3D particle emitter configuration", + "name": "SetStartSizeMax", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "StartSizeMax", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const startMaxSize = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setStartMaxSize(startMaxSize);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the end scale of the object.", + "fullName": "End scale", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter configuration", + "name": "EndScale", + "sentence": "the end scale", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyEndScale()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "EndScale", + "group": "3D particle emitter configuration", + "name": "SetEndScale", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "EndScale", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const endScale = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setEndScale(endScale);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the min start speed of the object.", + "fullName": "Min start speed", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter speed configuration", + "name": "StartSpeedMin", + "sentence": "the min start speed", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyStartSpeedMin()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "StartSpeedMin", + "group": "3D particle emitter speed configuration", + "name": "SetStartSpeedMin", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "StartSpeedMin", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const startSpeedMin = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setStartSpeedMin(startSpeedMin);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the max start speed of the object.", + "fullName": "Max start speed", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter speed configuration", + "name": "StartSpeedMax", + "sentence": "the max start speed", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyStartSpeedMax()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "StartSpeedMax", + "group": "3D particle emitter speed configuration", + "name": "SetStartSpeedMax", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "StartSpeedMax", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const startSpeedMax = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setStartSpeedMax(startSpeedMax);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the min lifespan of the object.", + "fullName": "Min lifespan", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter configuration", + "name": "LifespanMin", + "sentence": "the min lifespan", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyLifespanMin()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "LifespanMin", + "group": "3D particle emitter configuration", + "name": "SetLifespanMin", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "LifespanMin", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const lifespanMin = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setLifespanMin(lifespanMin);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the max lifespan of the object.", + "fullName": "Max lifespan", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter configuration", + "name": "LifespanMax", + "sentence": "the max lifespan", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyLifespanMax()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "LifespanMax", + "group": "3D particle emitter configuration", + "name": "SetLifespanMax", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "LifespanMax", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const lifespanMax = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setLifespanMax(lifespanMax);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the emission duration of the object.", + "fullName": "Emission duration", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter configuration", + "name": "Duration", + "sentence": "the emission duration", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyDuration()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Duration", + "group": "3D particle emitter configuration", + "name": "SetDuration", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Duration", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const duration = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setDuration(duration);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check if particles move with the emitter.", + "fullName": "Particles move with the emitter", + "functionType": "Condition", + "group": "3D particle emitter speed configuration", + "name": "AreParticlesRelative", + "sentence": "_PARAM0_ particles move with the emitter", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "AreParticlesRelative", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Change if particles move with the emitter.", + "fullName": "Particles move with the emitter", + "functionType": "Action", + "group": "3D particle emitter speed configuration", + "name": "SetAreParticlesRelative", + "sentence": "_PARAM0_ particles move with the emitter: _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "AreParticlesRelative", + "False", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "AreParticlesRelative", + "True", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const areParticlesRelative = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setParticlesRelative(areParticlesRelative);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + }, + { + "defaultValue": "yes", + "description": "AreParticlesRelative", + "name": "Value", + "optional": true, + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "the spay cone angle of the object.", + "fullName": "Spay cone angle", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter configuration", + "name": "SpayConeAngle", + "sentence": "the spay cone angle", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertySpayConeAngle()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "SpayConeAngle", + "group": "3D particle emitter configuration", + "name": "SetSpayConeAngle", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "SpayConeAngle", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const sprayConeAngle = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setSprayConeAngle(sprayConeAngle);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the blending of the object.", + "fullName": "Blending", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter color configuration", + "name": "Blending", + "sentence": "the blending", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnString" + }, + "parameters": [ + "Object.PropertyBlending()" + ] + } + ] + } + ], + "expressionType": { + "supplementaryInformation": "[\"Normal\",\"Additive\",\"Substractive\",\"Multiply\",\"None\"]", + "type": "stringWithSelector" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Blending", + "group": "3D particle emitter color configuration", + "name": "SetBlending", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Blending", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const blending = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setBlending(blending);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the gravity top of the object.", + "fullName": "Gravity top", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter speed configuration", + "name": "GravityTop", + "sentence": "the gravity top", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnString" + }, + "parameters": [ + "Object.PropertyGravityTop()" + ] + } + ] + } + ], + "expressionType": { + "supplementaryInformation": "[\"Y-\",\"Z+\"]", + "type": "stringWithSelector" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "GravityTop", + "group": "3D particle emitter speed configuration", + "name": "SetGravityTop", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "GravityTop", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const gravityTop = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setGravityTop(gravityTop);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the gravity of the object.", + "fullName": "Gravity", + "functionType": "ExpressionAndCondition", + "group": "3D particle emitter speed configuration", + "name": "Gravity", + "sentence": "the gravity", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.PropertyGravity()" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Gravity", + "group": "3D particle emitter speed configuration", + "name": "SetGravity", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Gravity", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const gravity = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__particleEmitterAdapter.setGravity(gravity);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check if delete when emission ends.", + "fullName": "Delete when emission ends", + "functionType": "Condition", + "group": "3D particle emitter configuration", + "name": "ShouldAutodestruct", + "sentence": "_PARAM0_ delete when emission ends", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "ShouldAutodestruct", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Change if delete when emission ends.", + "fullName": "Delete when emission ends", + "functionType": "Action", + "group": "3D particle emitter configuration", + "name": "SetShouldAutodestruct", + "sentence": "_PARAM0_ delete when emission ends: _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "ShouldAutodestruct", + "False", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "ShouldAutodestruct", + "True", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "ParticleEmitter3D::ParticleEmitter3D", + "type": "object" + }, + { + "defaultValue": "yes", + "description": "ShouldAutodestruct", + "name": "Value", + "optional": true, + "type": "yesorno" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onCreated" + }, + { + "functionName": "onDestroy" + }, + { + "functionName": "onHotReloading" + }, + { + "functionName": "UpdateFromProperties" + }, + { + "functionName": "UpdateHelper" + }, + { + "functionName": "UpdateImage" + }, + { + "functionName": "doStepPostEvents" + }, + { + "functionName": "RegisterInLayer" + }, + { + "functionName": "Delete" + }, + { + "functionName": "HasEnded" + }, + { + "functionName": "Restart" + }, + { + "folderName": "Position", + "children": [ + { + "functionName": "Z" + }, + { + "functionName": "SetZ" + } + ] + }, + { + "folderName": "Angle", + "children": [ + { + "functionName": "RotationX" + }, + { + "functionName": "SetRotationX" + }, + { + "functionName": "RotationY" + }, + { + "functionName": "SetRotationY" + } + ] + }, + { + "folderName": "3D particle emitter color configuration", + "children": [ + { + "functionName": "StartColor" + }, + { + "functionName": "SetStartColor" + }, + { + "functionName": "EndColor" + }, + { + "functionName": "SetEndColor" + }, + { + "functionName": "StartOpacity" + }, + { + "functionName": "SetStartOpacity" + }, + { + "functionName": "EndOpacity" + }, + { + "functionName": "SetEndOpacity" + }, + { + "functionName": "Blending" + }, + { + "functionName": "SetBlending" + } + ] + }, + { + "folderName": "3D particle emitter configuration", + "children": [ + { + "functionName": "Flow" + }, + { + "functionName": "SetFlow" + }, + { + "functionName": "StartSizeMin" + }, + { + "functionName": "SetStartSizeMin" + }, + { + "functionName": "StartSizeMax" + }, + { + "functionName": "SetStartSizeMax" + }, + { + "functionName": "EndScale" + }, + { + "functionName": "SetEndScale" + }, + { + "functionName": "LifespanMin" + }, + { + "functionName": "SetLifespanMin" + }, + { + "functionName": "LifespanMax" + }, + { + "functionName": "SetLifespanMax" + }, + { + "functionName": "Duration" + }, + { + "functionName": "SetDuration" + }, + { + "functionName": "SpayConeAngle" + }, + { + "functionName": "SetSpayConeAngle" + }, + { + "functionName": "ShouldAutodestruct" + }, + { + "functionName": "SetShouldAutodestruct" + } + ] + }, + { + "folderName": "3D particle emitter speed configuration", + "children": [ + { + "functionName": "StartSpeedMin" + }, + { + "functionName": "SetStartSpeedMin" + }, + { + "functionName": "StartSpeedMax" + }, + { + "functionName": "SetStartSpeedMax" + }, + { + "functionName": "AreParticlesRelative" + }, + { + "functionName": "SetAreParticlesRelative" + }, + { + "functionName": "GravityTop" + }, + { + "functionName": "SetGravityTop" + }, + { + "functionName": "Gravity" + }, + { + "functionName": "SetGravity" + } + ] + } + ] + }, + "propertyDescriptors": [ + { + "value": "255;0;0", + "type": "Color", + "label": "Start color", + "group": "Color", + "name": "StartColor" + }, + { + "value": "255;255;0", + "type": "Color", + "label": "End color", + "group": "Color", + "name": "EndColor" + }, + { + "value": "255", + "type": "Number", + "unit": "Dimensionless", + "label": "Start opacity", + "group": "Color", + "name": "StartOpacity" + }, + { + "value": "0", + "type": "Number", + "unit": "Dimensionless", + "label": "End opacity", + "group": "Color", + "name": "EndOpacity" + }, + { + "value": "50", + "type": "Number", + "label": "Flow of particles (particles per second)", + "name": "Flow" + }, + { + "value": "10", + "type": "Number", + "unit": "Pixel", + "label": "Start min size", + "group": "Size", + "name": "StartSizeMin" + }, + { + "value": "20", + "type": "Number", + "unit": "Pixel", + "label": "Start max size", + "group": "Size", + "name": "StartSizeMax" + }, + { + "value": "0", + "type": "Number", + "unit": "Dimensionless", + "label": "End scale", + "group": "Size", + "name": "EndScale" + }, + { + "value": "100", + "type": "Number", + "unit": "PixelSpeed", + "label": "Start min speed", + "group": "Speed", + "name": "StartSpeedMin" + }, + { + "value": "100", + "type": "Number", + "unit": "PixelSpeed", + "label": "Start max speed", + "group": "Speed", + "name": "StartSpeedMax" + }, + { + "value": "1", + "type": "Number", + "unit": "Second", + "label": "Min lifespan", + "name": "LifespanMin" + }, + { + "value": "2", + "type": "Number", + "unit": "Second", + "label": "Max lifespan", + "name": "LifespanMax" + }, + { + "value": "5", + "type": "Number", + "unit": "Second", + "label": "Emission duration", + "name": "Duration" + }, + { + "value": "", + "type": "Boolean", + "label": "Particles move with the emitter", + "group": "Speed", + "name": "AreParticlesRelative" + }, + { + "value": "30", + "type": "Number", + "unit": "DegreeAngle", + "label": "Spay cone angle", + "group": "Position", + "name": "SpayConeAngle" + }, + { + "value": "Additive", + "type": "Choice", + "label": "Blending", + "group": "Color", + "choices": [ + { + "label": "Normal", + "value": "Normal" + }, + { + "label": "Additive", + "value": "Additive" + }, + { + "label": "Subtractive", + "value": "Subtractive" + }, + { + "label": "Multiply", + "value": "Multiply" + }, + { + "label": "None", + "value": "None" + } + ], + "name": "Blending" + }, + { + "value": "Y-", + "type": "Choice", + "label": "Gravity top", + "group": "Speed", + "choices": [ + { + "label": "Y-", + "value": "Y-" + }, + { + "label": "Z+", + "value": "Z+" + } + ], + "name": "GravityTop" + }, + { + "value": "0", + "type": "Number", + "unit": "PixelAcceleration", + "label": "Gravity", + "group": "Speed", + "name": "Gravity" + }, + { + "value": "true", + "type": "Boolean", + "label": "Delete when emission ends", + "name": "ShouldAutodestruct" + }, + { + "value": "Center-center", + "type": "String", + "label": "", + "description": "Only used by the scene editor.", + "hidden": true, + "name": "ParentOrigin" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Z (elevation)", + "description": "Deprecated", + "group": "Position", + "hidden": true, + "name": "Z" + }, + { + "value": "0", + "type": "Number", + "unit": "DegreeAngle", + "label": "Rotation on X axis", + "group": "Position", + "hidden": true, + "name": "RotationX" + }, + { + "value": "0", + "type": "Number", + "unit": "DegreeAngle", + "label": "Rotation on Y axis", + "group": "Position", + "hidden": true, + "name": "RotationY" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "folderName": "Color", + "children": [ + { + "propertyName": "StartColor" + }, + { + "propertyName": "EndColor" + }, + { + "propertyName": "StartOpacity" + }, + { + "propertyName": "EndOpacity" + }, + { + "propertyName": "Blending" + } + ] + }, + { + "propertyName": "Flow" + }, + { + "folderName": "Size", + "children": [ + { + "propertyName": "StartSizeMin" + }, + { + "propertyName": "StartSizeMax" + }, + { + "propertyName": "EndScale" + } + ] + }, + { + "folderName": "Speed", + "children": [ + { + "propertyName": "StartSpeedMin" + }, + { + "propertyName": "StartSpeedMax" + }, + { + "propertyName": "AreParticlesRelative" + }, + { + "propertyName": "GravityTop" + }, + { + "propertyName": "Gravity" + } + ] + }, + { + "propertyName": "LifespanMin" + }, + { + "propertyName": "LifespanMax" + }, + { + "propertyName": "Duration" + }, + { + "folderName": "Position", + "children": [ + { + "propertyName": "SpayConeAngle" + }, + { + "propertyName": "Z" + }, + { + "propertyName": "RotationX" + }, + { + "propertyName": "RotationY" + } + ] + }, + { + "propertyName": "ShouldAutodestruct" + }, + { + "propertyName": "ParentOrigin" + } + ] + }, + "variants": [] + } + ] + }, + { + "author": "VegeTato, arthuro555", + "category": "General", + "dimension": "", + "extensionNamespace": "", + "fullName": "Repeat every X seconds", + "gdevelopVersion": ">=5.5.222", + "helpPath": "", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0ibWRpLXJlcGVhdCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxwYXRoIGQ9Ik0xNywxN0g3VjE0TDMsMThMNywyMlYxOUgxOVYxM0gxN003LDdIMTdWMTBMMjEsNkwxNywyVjVINVYxMUg3VjdaIiAvPjwvc3ZnPg==", + "name": "RepeatEveryXSeconds", + "previewIconUrl": "https://resources.gdevelop-app.com/assets/Icons/repeat.svg", + "shortDescription": "Trigger an event every X seconds.", + "version": "0.2.1", + "description": "Convenience conditions, actions and behaviors for timers to trigger a condition every X seconds.", + "origin": { + "identifier": "RepeatEveryXSeconds", + "name": "gdevelop-extension-store" + }, + "tags": [ + "repeat", + "timer", + "time" + ], + "authorIds": [ + "ZgrsWuRTAkXgeuPV9bo0zuEcA2w1", + "IRIhkkTTl2UHhfjrLTTH5GYwkYu1", + "IWykYNRvhCZBN3vEgKEbBPOR3Oc2" + ], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [], + "eventsFunctions": [ + { + "description": "Triggers every X seconds.", + "fullName": "Repeat with a scene timer", + "functionType": "Condition", + "name": "Repeat", + "sentence": "Repeat every _PARAM2_ seconds using timer _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "CompareTimer" + }, + "parameters": [ + "", + "TimerName", + ">=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "ResetTimer" + }, + "parameters": [ + "player", + "TimerName" + ] + }, + { + "type": { + "value": "ModVarScene" + }, + "parameters": [ + "__RepeatEveryXSeconds.Repetitions[TimerName]", + "=", + "0" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "TODO: It should keep the overflowing time to be more precise (it would need JavaScript)" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CompareTimer" + }, + "parameters": [ + "player", + "TimerName", + ">=", + "LoopDuration" + ] + } + ], + "actions": [ + { + "type": { + "value": "ResetTimer" + }, + "parameters": [ + "player", + "TimerName" + ] + }, + { + "type": { + "value": "ModVarScene" + }, + "parameters": [ + "__RepeatEveryXSeconds.Repetitions[TimerName]", + "+", + "1" + ] + }, + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Timer name used to loop", + "name": "TimerName", + "type": "string" + }, + { + "description": "Duration in seconds between each repetition", + "name": "LoopDuration", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the number of times the timer has repeated.", + "fullName": "Repetition number of a scene timer", + "functionType": "ExpressionAndCondition", + "name": "Repetition", + "sentence": "Repetition number of timer _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Variable(__RepeatEveryXSeconds.Repetitions[TimerName])" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Timer name used to loop", + "name": "TimerName", + "type": "string" + } + ], + "objectGroups": [] + }, + { + "description": "Triggers every X seconds X amount of times.", + "fullName": "Repeat with a scene timer X times", + "functionType": "Condition", + "name": "RepeatXTimes", + "sentence": "Repeat every _PARAM2_ seconds _PARAM3_ times using timer _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "MaxLoop", + "<", + "0" + ] + }, + { + "type": { + "value": "RepeatEveryXSeconds::Repetition" + }, + "parameters": [ + "", + "<", + "MaxLoop", + "TimerName", + "" + ] + } + ] + }, + { + "type": { + "value": "RepeatEveryXSeconds::Repeat" + }, + "parameters": [ + "", + "TimerName", + "LoopDuration", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Timer name used to loop", + "name": "TimerName", + "type": "string" + }, + { + "description": "Duration in seconds between each repetition", + "name": "LoopDuration", + "type": "expression" + }, + { + "description": "The limit of loops", + "longDescription": "Maximum nuber of repetition (-1 to repeat forever).", + "name": "MaxLoop", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Reset repetition count of a scene timer.", + "fullName": "Reset repetition count of a scene timer", + "functionType": "Action", + "name": "DeleteTimer", + "sentence": "Reset repetition count for timer _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "RemoveTimer" + }, + "parameters": [ + "player", + "TimerName" + ] + }, + { + "type": { + "value": "VariableRemoveChild" + }, + "parameters": [ + "__RepeatEveryXSeconds.Repetitions", + "TimerName" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Timer name used to loop", + "name": "TimerName", + "type": "string" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "Repeat" + }, + { + "functionName": "Repetition" + }, + { + "functionName": "RepeatXTimes" + }, + { + "functionName": "DeleteTimer" + } + ] + }, + "eventsBasedBehaviors": [ + { + "description": "Allows to repeat an object timer every X seconds.", + "fullName": "Repeat every X seconds", + "helpPath": "", + "iconUrl": "", + "name": "RepeatTimer", + "objectType": "", + "previewIconUrl": "", + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onCreated", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ResetObjectTimer" + }, + "parameters": [ + "Object", + "TimerName" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "RepeatEveryXSeconds::RepeatTimer", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Triggers every X seconds.", + "fullName": "Repeat with an object timer", + "functionType": "Condition", + "group": "Timers", + "name": "Repeat2", + "sentence": "Repeat every _PARAM3_ seconds using timer _PARAM2_ of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "CompareObjectTimer" + }, + "parameters": [ + "Object", + "TimerName", + ">=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "ResetObjectTimer" + }, + "parameters": [ + "Object", + "TimerName" + ] + }, + { + "type": { + "value": "ModVarObjet" + }, + "parameters": [ + "Object", + "__RepeatEveryXSeconds.Repetitions[TimerName]", + "=", + "0" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "TODO: It should keep the overflowing time to be more precise (it would need JavaScript)" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CompareObjectTimer" + }, + "parameters": [ + "Object", + "TimerName", + ">=", + "LoopDuration" + ] + } + ], + "actions": [ + { + "type": { + "value": "ResetObjectTimer" + }, + "parameters": [ + "Object", + "TimerName" + ] + }, + { + "type": { + "value": "ModVarObjet" + }, + "parameters": [ + "Object", + "__RepeatEveryXSeconds.Repetitions[TimerName]", + "+", + "1" + ] + }, + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "RepeatEveryXSeconds::RepeatTimer", + "type": "behavior" + }, + { + "description": "Timer name used to loop", + "name": "TimerName", + "type": "string" + }, + { + "description": "Duration in seconds between each repetition", + "name": "LoopDuration", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the number of times the timer has repeated.", + "fullName": "Repetition number of an object timer", + "functionType": "ExpressionAndCondition", + "group": "Timers", + "name": "Repetition", + "sentence": "Repetition number of timer _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Object.Variable(__RepeatEveryXSeconds.Repetitions[TimerName])" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "RepeatEveryXSeconds::RepeatTimer", + "type": "behavior" + }, + { + "description": "Timer name used to loop", + "name": "TimerName", + "type": "string" + } + ], + "objectGroups": [] + }, + { + "description": "Triggers every X seconds X amount of times.", + "fullName": "Repeat with an object timer X times", + "functionType": "Condition", + "group": "Timers", + "name": "RepeatXTimes", + "sentence": "Repeat every _PARAM3_ seconds _PARAM4_ times using timer _PARAM2_ of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "MaxLoop", + "<", + "0" + ] + }, + { + "type": { + "value": "RepeatEveryXSeconds::RepeatTimer::Repetition" + }, + "parameters": [ + "Object", + "Behavior", + "<", + "MaxLoop", + "TimerName", + "" + ] + } + ] + }, + { + "type": { + "value": "RepeatEveryXSeconds::RepeatTimer::Repeat2" + }, + "parameters": [ + "Object", + "Behavior", + "TimerName", + "LoopDuration", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "RepeatEveryXSeconds::RepeatTimer", + "type": "behavior" + }, + { + "description": "Timer name used to loop", + "name": "TimerName", + "type": "string" + }, + { + "description": "Duration in seconds between each repetition", + "name": "LoopDuration", + "type": "expression" + }, + { + "description": "The limit of loops", + "longDescription": "Maximum nuber of repetition (-1 to repeat forever).", + "name": "MaxLoop", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Reset repetition count of an object timer.", + "fullName": "Reset repetition count of an object timer", + "functionType": "Action", + "group": "Timers", + "name": "DeleteTimer", + "sentence": "Reset repetition count for timer _PARAM2_ of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "RemoveObjectTimer" + }, + "parameters": [ + "Object", + "TimerName" + ] + }, + { + "type": { + "value": "ObjectVariableRemoveChild" + }, + "parameters": [ + "Object", + "__RepeatEveryXSeconds.Repetitions", + "TimerName" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "RepeatEveryXSeconds::RepeatTimer", + "type": "behavior" + }, + { + "description": "Timer name used to loop", + "name": "TimerName", + "type": "string" + } + ], + "objectGroups": [] + }, + { + "description": "Triggers every X seconds, where X is defined in the behavior properties.", + "fullName": "Repeat every X seconds (deprecated)", + "functionType": "Condition", + "name": "Repeat", + "private": true, + "sentence": "Recurring timer _PARAM1_ of _PARAM0_ has triggered", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "ObjectTimer" + }, + "parameters": [ + "Object", + "TimerName", + "TimerLength" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Limit", + "=", + "-1" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "Counter", + "<", + "Limit" + ] + } + ] + } + ], + "actions": [ + { + "type": { + "value": "ResetObjectTimer" + }, + "parameters": [ + "Object", + "TimerName" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Counter", + "+", + "1" + ] + }, + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "RepeatEveryXSeconds::RepeatTimer", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Pauses a recurring timer.", + "fullName": "Pause a recurring timer (deprecated)", + "functionType": "Action", + "name": "Pause", + "private": true, + "sentence": "Pause recurring timer _PARAM1_ of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "PauseObjectTimer" + }, + "parameters": [ + "Object", + "TimerName" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "RepeatEveryXSeconds::RepeatTimer", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Resumes a paused recurring timer.", + "fullName": "Resume a recurring timer (deprecated)", + "functionType": "Action", + "name": "Resume", + "private": true, + "sentence": "Resume recurring timer _PARAM1_ of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "UnPauseObjectTimer" + }, + "parameters": [ + "Object", + "TimerName" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "RepeatEveryXSeconds::RepeatTimer", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Allows to trigger the recurring timer X times again.", + "fullName": "Reset the limit (deprecated)", + "functionType": "Action", + "name": "ResetLimit", + "private": true, + "sentence": "Allow to trigger the recurring timer _PARAM1_ of _PARAM0_ X times again", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Counter", + "=", + "0" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "RepeatEveryXSeconds::RepeatTimer", + "type": "behavior" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onCreated" + }, + { + "folderName": "Timers", + "children": [ + { + "functionName": "Repeat2" + }, + { + "functionName": "Repetition" + }, + { + "functionName": "RepeatXTimes" + }, + { + "functionName": "DeleteTimer" + } + ] + }, + { + "functionName": "Repeat" + }, + { + "functionName": "Pause" + }, + { + "functionName": "Resume" + }, + { + "functionName": "ResetLimit" + } + ] + }, + "propertyDescriptors": [ + { + "value": "MyTimer", + "type": "String", + "label": "The name of the timer to repeat", + "deprecated": true, + "name": "TimerName" + }, + { + "value": "1", + "type": "Number", + "label": "The time between each trigger (in seconds)", + "deprecated": true, + "name": "TimerLength" + }, + { + "value": "-1", + "type": "Number", + "label": "How many times should the timer trigger? -1 for forever.", + "deprecated": true, + "name": "Limit" + }, + { + "value": "0", + "type": "Number", + "label": "An internal counter", + "hidden": true, + "name": "Counter" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "TimerName" + }, + { + "propertyName": "TimerLength" + }, + { + "propertyName": "Limit" + }, + { + "propertyName": "Counter" + } + ] + } + } + ], + "eventsBasedObjects": [] + }, + { + "author": "", + "category": "General", + "dimension": "", + "extensionNamespace": "", + "fullName": "3D collision", + "gdevelopVersion": ">=5.5.222", + "helpPath": "", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0ibWRpLXZlY3Rvci1pbnRlcnNlY3Rpb24iIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMy4xNCwxQTIuMTQsMi4xNCAwIDAsMCAxLDMuMTRWNUgzVjNINVYxSDMuMTRNNywxVjNIMTBWMUg3TTEyLDFWM0gxNFY1SDE2VjMuMTRDMTYsMS45NiAxNS4wNCwxIDEzLjg2LDFIMTJNMSw3VjEwSDNWN0gxTTksN0M3Ljg5LDcgNyw3Ljg5IDcsOUM3LDExLjMzIDcsMTYgNywxNkM3LDE2IDExLjU3LDE2IDEzLjg2LDE2QTIuMTQsMi4xNCAwIDAsMCAxNiwxMy44NkMxNiwxMS41NyAxNiw3IDE2LDdDMTYsNyAxMS4zMyw3IDksN00xOCw3VjlIMjBWMTFIMjJWOUMyMiw3Ljg5IDIxLjExLDcgMjAsN0gxOE05LDlIMTRWMTRIOVY5TTEsMTJWMTMuODZDMSwxNS4wNCAxLjk2LDE2IDMuMTQsMTZINVYxNEgzVjEySDFNMjAsMTNWMTZIMjJWMTNIMjBNNywxOFYyMEM3LDIxLjExIDcuODksMjIgOSwyMkgxMVYyMEg5VjE4SDdNMjAsMThWMjBIMThWMjJIMjBDMjEuMTEsMjIgMjIsMjEuMTEgMjIsMjBWMThIMjBNMTMsMjBWMjJIMTZWMjBIMTNaIiAvPjwvc3ZnPg==", + "name": "Collision3D", + "previewIconUrl": "https://asset-resources.gdevelop.io/public-resources/Icons/7a5696a515bf40813692e118147568392a854f65f5b50750c9b9aaa967aba7df_vector-intersection.svg", + "shortDescription": "Check collision and distance between 3D objects.", + "version": "0.2.1", + "description": "Check collision and distance between 3D objects and separate them from each other.", + "origin": { + "identifier": "Collision3D", + "name": "gdevelop-extension-store" + }, + "tags": [ + "3d", + "collision" + ], + "authorIds": [ + "IWykYNRvhCZBN3vEgKEbBPOR3Oc2", + "PEzPAaWHgYgk5UwIPppsL6f2ugp2" + ], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [], + "eventsFunctions": [ + { + "description": "Define helper classes JavaScript code.", + "fullName": "Define helper classes", + "functionType": "Action", + "name": "DefineHelperClasses", + "private": true, + "sentence": "Define helper classes JavaScript code", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "if (gdjs._collision3DExtension) {", + " return;", + "}", + "", + "/**", + " * @param {gdjs.RuntimeObject} object", + " * @param {boolean} shouldUseCustomCenter", + " * @return {number}", + " */", + "const getCenterX = (object, shouldUseCustomCenter) =>", + " shouldUseCustomCenter ?", + " object.getCenterXInScene() :", + " object.getDrawableX() + object.getWidth() / 2", + "", + "/**", + " * @param {gdjs.RuntimeObject} object", + " * @param {boolean} shouldUseCustomCenter", + " * @return {number}", + " */", + "const getCenterY = (object, shouldUseCustomCenter) =>", + " shouldUseCustomCenter ?", + " object.getCenterYInScene() :", + " object.getDrawableY() + object.getHeight() / 2", + "", + "/**", + " * @param {gdjs.RuntimeObject3D} object", + " * @param {boolean} shouldUseCustomCenter", + " * @return {number}", + " */", + "const getCenterZ = (object, shouldUseCustomCenter) =>", + " !object.getCenterZInScene ? 0 :", + " shouldUseCustomCenter ?", + " object.getCenterZInScene() :", + " object.getDrawableZ() + object.getDepth() / 2", + "", + "/**", + " * @param {gdjs.RuntimeObject} object", + " * @param {float} x", + " * @param {float} y", + " * @param {float} z", + " * @param {boolean} shouldUseCustomCenter", + " * @return {number}", + " */", + "const getSqDistanceToPosition = (object, x, y, z, shouldUseCustomCenter = true) => {", + " const deltaX = getCenterX(object, shouldUseCustomCenter) - x;", + " const deltaY = getCenterY(object, shouldUseCustomCenter) - y;", + " const deltaZ = getCenterZ(object, shouldUseCustomCenter) - z;", + " return deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;", + "};", + "", + "/**", + " * @param {gdjs.RuntimeObject} object", + " * @param {float} x", + " * @param {float} y", + " * @param {float} z", + " * @return {number}", + " */", + "const getDistanceToPosition = (object, x, y, z) => Math.sqrt(getSqDistanceToPosition(object, x, y, z));", + "", + "/**", + " * @param {gdjs.RuntimeObject} object", + " * @param {gdjs.RuntimeObject} otherObject", + " * @param {boolean} shouldUseCustomCenter", + " * @return {number}", + " */", + "const getSqDistanceToObject = (object, otherObject, shouldUseCustomCenter = true) => {", + " return getSqDistanceToPosition(", + " object,", + " getCenterX(otherObject, shouldUseCustomCenter),", + " getCenterY(otherObject, shouldUseCustomCenter),", + " getCenterZ(otherObject, shouldUseCustomCenter)", + " );", + "};", + "", + "/**", + " * @param {gdjs.RuntimeObject} object", + " * @param {gdjs.RuntimeObject} otherObject", + " * @return {number}", + " */", + "const getDistanceToObject = (object, otherObject) => Math.sqrt(getSqDistanceToObject(object, otherObject));", + "", + "/**", + " * @param {gdjs.RuntimeObject} object", + " * @param {gdjs.RuntimeObject} otherObject", + " * @param {{distanceSq: number, shouldUseCustomCenter: boolean}} distanceSettings", + " * @return {boolean}", + " */", + "const areObjectsWithinDistance = (object, otherObject, distanceSettings) => {", + " return getSqDistanceToObject(", + " object, otherObject, distanceSettings.shouldUseCustomCenter) <= distanceSettings.distanceSq;", + "};", + "", + "const distanceSettings = {distanceSq: 0, shouldUseCustomCenter: true};", + "", + "/**", + " * @param {Hashtable} objectsLists1", + " * @param {Hashtable} objectsLists2", + " * @param {number} distance", + " * @param {boolean} shouldUseCustomCenter", + " * @param {boolean} inverted", + " * @return {boolean}", + " */", + "const pickObjectsWithinDistance = (objectsLists1, objectsLists2, distance, shouldUseCustomCenter, inverted) => {", + " distanceSettings.distanceSq = distance * distance;", + " distanceSettings.shouldUseCustomCenter = shouldUseCustomCenter;", + " return gdjs.evtTools.object.twoListsTest(", + " areObjectsWithinDistance,", + " objectsLists1,", + " objectsLists2,", + " inverted,", + " distanceSettings", + " );", + "}", + "", + "/**", + " * @param {Hashtable} objectsLists", + " * @param {number} x", + " * @param {number} y", + " * @param {number} z", + " * @param {boolean} inverted", + " * @return {boolean}", + " */", + "const pickNearestObject = function (objectsLists, x, y, z, inverted) {", + " let bestObject = null;", + " let best = 0;", + " let first = true;", + " const lists = gdjs.staticArray(gdjs._collision3DExtension.pickNearestObject);", + " objectsLists.values(lists);", + " for (let i = 0, len = lists.length; i < len; ++i) {", + " const list = lists[i];", + " for (let j = 0; j < list.length; ++j) {", + " const object = list[j];", + " const distance = getSqDistanceToPosition(object, x, y, z);", + " // @ts-ignore", + " if (first || (distance < best) ^ inverted) {", + " best = distance;", + " bestObject = object;", + " }", + " first = false;", + " }", + " }", + " if (bestObject) {", + " gdjs.evtTools.object.pickOnly(objectsLists, bestObject);", + " }", + " return !!bestObject;", + "}", + "", + "/**", + " * @param {gdjs.RuntimeObject} object", + " * @return {float}", + " */", + "const getObjectMinZ = (object) =>", + " object.getDrawableZ ? object.getDrawableZ() : 0", + "", + "/**", + " * @param {gdjs.RuntimeObject} object", + " * @return {float}", + " */", + "const getObjectMaxZ = (object) =>", + " object.getDrawableZ ? object.getDrawableZ() + object.getDepth() : 0;", + "", + "/**", + " * @param {gdjs.RuntimeObject} object1", + " * @param {gdjs.RuntimeObject} object2", + " * @param {boolean} ignoreTouchingEdges If true, then edges that are touching each other, without the hitbox polygons actually overlapping, won't be considered in collision.", + " * @return {boolean}", + " */", + "const areObjectsInCollision = (", + " object1,", + " object2,", + " ignoreTouchingEdges,", + ") => {", + " const object1MinZ = getObjectMinZ(object1);", + " const object1MaxZ = getObjectMaxZ(object1);", + " const object2MinZ = getObjectMinZ(object2);", + " const object2MaxZ = getObjectMaxZ(object2);", + "", + " const canObjectsOverlapOnZ = ignoreTouchingEdges ?", + " (object1MinZ < object2MaxZ && object1MaxZ > object2MinZ) :", + " (object1MinZ <= object2MaxZ && object1MaxZ >= object2MinZ);", + "", + " return canObjectsOverlapOnZ &&", + " gdjs.RuntimeObject.collisionTest(", + " object1,", + " object2,", + " ignoreTouchingEdges", + " );", + "}", + "", + "/**", + " * @param {Hashtable} objectsLists1", + " * @param {Hashtable} objectsLists2", + " * @param {boolean} inverted", + " * @return {boolean}", + " */", + "const pickObjectsInCollision = (", + " objectsLists1,", + " objectsLists2,", + " inverted,", + ") => {", + " return gdjs.evtTools.object.twoListsTest(", + " areObjectsInCollision,", + " objectsLists1,", + " objectsLists2,", + " inverted,", + " false", + " );", + "}", + "", + "/**", + " * @param {gdjs.RuntimeObject} movingObject", + " * @param {gdjs.RuntimeObject} object", + " * @return {float}", + " */", + "const getSeparationDeltaZ = (", + " movingObject,", + " object,", + ") => {", + " const movingObjectMinZ = getObjectMinZ(movingObject);", + " const movingObjectMaxZ = getObjectMaxZ(movingObject);", + " const objectMinZ = getObjectMinZ(object);", + " const objectMaxZ = getObjectMaxZ(object);", + "", + " const downwardDeltaZ = Math.min(0, objectMinZ - movingObjectMaxZ);", + " const upwardDeltaZ = Math.max(0, objectMaxZ - movingObjectMinZ);", + "", + " return -downwardDeltaZ < upwardDeltaZ ? downwardDeltaZ : upwardDeltaZ", + "}", + "", + "// This function is an exact copy from GDJS/Runtime/runtimeobject.ts", + "/**", + " * Move the object using the results from collisionTest call.", + " * This moves the object according to the direction of the longest vector,", + " * and projects the others on the orthogonal vector.", + " *", + " * See {@link RuntimeObject.separateFromObjects}", + " *", + " * @param {gdjs.RuntimeObject} object The object to move.", + " * @param {float[]} moveXArray The X coordinates of the vectors to move the object.", + " * @param {float[]} moveYArray The Y coordinates of the vectors to move the object.", + " * @return {boolean} true if the object was moved.", + " */", + "const moveFollowingSeparatingVectors = (", + " object,", + " moveXArray,", + " moveYArray", + ") => {", + " if (moveXArray.length === 0) {", + " moveXArray.length = 0;", + " moveYArray.length = 0;", + " return false;", + " }", + " if (moveXArray.length === 1) {", + " // Move according to the results returned by the collision algorithm.", + " object.setPosition(", + " object.getX() + moveXArray[0],", + " object.getY() + moveYArray[0]", + " );", + " moveXArray.length = 0;", + " moveYArray.length = 0;", + " return true;", + " }", + "", + " // Find the longest vector", + " let squaredDistanceMax = 0;", + " let distanceMaxIndex = 0;", + " for (let index = 0; index < moveXArray.length; index++) {", + " const moveX = moveXArray[index];", + " const moveY = moveYArray[index];", + "", + " const squaredDistance = moveX * moveX + moveY * moveY;", + " if (squaredDistance > squaredDistanceMax) {", + " squaredDistanceMax = squaredDistance;", + " distanceMaxIndex = index;", + " }", + " }", + "", + " const distanceMax = Math.sqrt(squaredDistanceMax);", + " // unit vector of the longest vector", + " const uX = moveXArray[distanceMaxIndex] / distanceMax;", + " const uY = moveYArray[distanceMaxIndex] / distanceMax;", + "", + " // normal vector of the longest vector", + " const vX = -uY;", + " const vY = uX;", + "", + " // Project other vectors on the normal", + " let scalarProductMin = 0;", + " let scalarProductMax = 0;", + " for (let index = 0; index < moveXArray.length; index++) {", + " const moveX = moveXArray[index];", + " const moveY = moveYArray[index];", + "", + " const scalarProduct = moveX * vX + moveY * vY;", + " scalarProductMin = Math.min(scalarProductMin, scalarProduct);", + " scalarProductMax = Math.max(scalarProductMax, scalarProduct);", + " }", + "", + " // Apply the longest vector", + " let deltaX = moveXArray[distanceMaxIndex];", + " let deltaY = moveYArray[distanceMaxIndex];", + "", + " // Apply the longest projected vector if they all are in the same direction", + " // Some projections could have rounding errors,", + " // they are considered negligible under a 1 for 1,000,000 ratio.", + " const scalarProductMinIsNegligible =", + " -scalarProductMin < scalarProductMax / 1048576;", + " const scalarProductMaxIsNegligible =", + " scalarProductMax < -scalarProductMin / 1048576;", + " if (scalarProductMinIsNegligible !== scalarProductMaxIsNegligible) {", + " if (scalarProductMaxIsNegligible) {", + " deltaX += scalarProductMin * vX;", + " deltaY += scalarProductMin * vY;", + " } else {", + " deltaX += scalarProductMax * vX;", + " deltaY += scalarProductMax * vY;", + " }", + " }", + " object.setPosition(object.getX() + deltaX, object.getY() + deltaY);", + " moveXArray.length = 0;", + " moveYArray.length = 0;", + " return true;", + "};", + "", + "/**", + " * Arrays and data structure that are (re)used by", + " * {@link separateFromObjects} to avoid any allocation.", + " * @type {{moveXArray: float[], moveYArray: float[], moveZArray: float[]}}", + " */", + "const separateFromObjectsStatics = {", + " moveXArray: [],", + " moveYArray: [],", + " moveZArray: [],", + "};", + "", + "/**", + " * Separate the object from others objects, using their hitboxes.", + " * @param {gdjs.RuntimeObject} object The object that moves.", + " * @param {gdjs.RuntimeObject[]} objects The objects that stay still.", + " * @return {boolean} true if the object was moved", + " */", + "const separateFromObjects = (", + " object,", + " objects", + ") => {", + " const moveXArray = separateFromObjectsStatics.moveXArray;", + " const moveYArray = separateFromObjectsStatics.moveYArray;", + " moveXArray.length = 0;", + " moveYArray.length = 0;", + " let moveZMax = 0;", + "", + " // We can assume that the moving object is not grid based,", + " // so there is no need for optimization:", + " // getHitBoxes can be called directly.", + " const hitBoxes = object.getHitBoxes();", + " /** @type {gdjs.AABB | null} */", + " let aabb = null;", + "", + " // Check if there is a collision with each object", + " for (const otherObject of objects) {", + " if (otherObject.id === object.id) {", + " continue;", + " }", + " const moveZ = getSeparationDeltaZ(object, otherObject);", + " if (moveZ === 0) {", + " continue;", + " }", + " const moveZSq = moveZ * moveZ;", + "", + " let otherHitBoxesArray = otherObject.getHitBoxes();", + " /** @type {Iterable} */", + " let otherHitBoxes = otherHitBoxesArray;", + " if (otherHitBoxesArray.length > 4) {", + " // The other object has a lot of hit boxes.", + " // Try to reduce the amount of hitboxes to check.", + " if (!aabb) {", + " aabb = object.getAABB();", + " }", + " otherHitBoxes = otherObject.getHitBoxesAround(", + " aabb.min[0],", + " aabb.min[1],", + " aabb.max[0],", + " aabb.max[1]", + " );", + " }", + " for (const hitBox of hitBoxes) {", + " for (const otherHitBox of otherHitBoxes) {", + " const result = gdjs.Polygon.collisionTest(", + " hitBox,", + " otherHitBox,", + " true", + " );", + " if (result.collision) {", + " const moveX = result.move_axis[0];", + " const moveY = result.move_axis[1];", + " if (moveZSq < moveX * moveX + moveY * moveY) {", + " if (Math.abs(moveZ) > Math.abs(moveZMax)) {", + " moveZMax = moveZ;", + " }", + " }", + " else {", + " moveXArray.push(moveX);", + " moveYArray.push(moveY);", + " }", + " }", + " }", + " }", + " }", + " const hasObjectMovedOnZ = moveZMax !== 0;", + " if (hasObjectMovedOnZ) {", + " object.setZ(object.getZ() + moveZMax);", + " }", + " const hasObjectMovedOnXY = moveFollowingSeparatingVectors(object, moveXArray, moveYArray);", + " return hasObjectMovedOnXY || hasObjectMovedOnZ;", + "}", + "", + "gdjs._collision3DExtension = {", + " getSqDistanceToPosition,", + " getDistanceToPosition,", + " getSqDistanceToObject,", + " getDistanceToObject,", + " pickObjectsWithinDistance,", + " pickNearestObject,", + " pickObjectsInCollision,", + " separateFromObjects", + "}" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onFirstSceneLoaded", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Collision3D::DefineHelperClasses" + }, + "parameters": [ + "", + "" + ] + } + ] + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "Compare the distance between two objects in 3D.", + "fullName": "Distance between two objects in 3D", + "functionType": "Condition", + "group": "Position", + "name": "AreWithinDistance", + "sentence": "_PARAM1_ distance to _PARAM2_ is below _PARAM3_ pixels", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "// TODO If condition is inverted, only objects that have a distance greater than specified to any other object will be picked.\r", + "const inverted = false;\r", + "\r", + "eventsFunctionContext.returnValue = gdjs._collision3DExtension.pickObjectsWithinDistance(\r", + " eventsFunctionContext.getObjectsLists(\"Object\"),\r", + " eventsFunctionContext.getObjectsLists(\"OtherObject\"),\r", + " eventsFunctionContext.getArgument(\"Distance\"),\r", + " eventsFunctionContext.getArgument(\"ShouldUseCustomCenter\"),\r", + " inverted\r", + ");\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "objectList" + }, + { + "description": "Other object", + "name": "OtherObject", + "type": "objectList" + }, + { + "description": "Distance", + "name": "Distance", + "type": "expression" + }, + { + "defaultValue": "yes", + "description": "Use custom center", + "name": "ShouldUseCustomCenter", + "optional": true, + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "Distance between two objects in 3D.", + "fullName": "Distance between two objects in 3D", + "functionType": "Expression", + "group": "Position", + "name": "Distance", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const otherObjects = eventsFunctionContext.getObjects(\"OtherObject\");\r", + "\r", + "if (objects.length > 0 && otherObjects.length > 0) {\r", + " eventsFunctionContext.returnValue = gdjs._collision3DExtension.getDistanceToObject(\r", + " objects[0],\r", + " otherObjects[0]\r", + " );\r", + "}\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "objectList" + }, + { + "description": "Other object", + "name": "OtherObject", + "type": "objectList" + } + ], + "objectGroups": [] + }, + { + "description": "Square distance between two objects in 3D.", + "fullName": "Square distance between two objects", + "functionType": "Expression", + "group": "Position", + "name": "SqDistance", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const otherObjects = eventsFunctionContext.getObjects(\"OtherObject\");\r", + "\r", + "if (objects.length > 0 && otherObjects.length > 0) {\r", + " eventsFunctionContext.returnValue = gdjs._collision3DExtension.getSqDistanceToObject(\r", + " objects[0],\r", + " otherObjects[0]\r", + " );\r", + "}\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "objectList" + }, + { + "description": "Other object", + "name": "OtherObject", + "type": "objectList" + } + ], + "objectGroups": [] + }, + { + "description": "Distance between an object and a position in 3D.", + "fullName": "Distance between an object and a position", + "functionType": "Expression", + "group": "Position", + "name": "DistanceToPosition", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "if (objects.length > 0) {\r", + " eventsFunctionContext.returnValue = gdjs._collision3DExtension.getDistanceToPosition(\r", + " objects[0],\r", + " eventsFunctionContext.getArgument(\"PositionX\"),\r", + " eventsFunctionContext.getArgument(\"PositionY\"),\r", + " eventsFunctionContext.getArgument(\"PositionZ\"),\r", + " );\r", + "}\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "objectList" + }, + { + "description": "X position", + "name": "PositionX", + "type": "expression" + }, + { + "description": "Y position", + "name": "PositionY", + "type": "expression" + }, + { + "description": "Z position", + "name": "PositionZ", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Square distance between an object and a position in 3D.", + "fullName": "Square distance between an object and a position", + "functionType": "Expression", + "group": "Position", + "name": "SqDistanceToPosition", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "if (objects.length > 0) {\r", + " eventsFunctionContext.returnValue = gdjs._collision3DExtension.getSqDistanceToPosition(\r", + " objects[0],\r", + " eventsFunctionContext.getArgument(\"PositionX\"),\r", + " eventsFunctionContext.getArgument(\"PositionY\"),\r", + " eventsFunctionContext.getArgument(\"PositionZ\"),\r", + " );\r", + "}\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "objectList" + }, + { + "description": "X position", + "name": "PositionX", + "type": "expression" + }, + { + "description": "Y position", + "name": "PositionY", + "type": "expression" + }, + { + "description": "Z position", + "name": "PositionZ", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Pick the object of this type that is nearest to the specified position in 3D.", + "fullName": "Pick nearest object in 3D", + "functionType": "Condition", + "group": "Objects", + "name": "PickNearest", + "sentence": "Pick the _PARAM1_ that is nearest to _PARAM2_ ; _PARAM3_ ; _PARAM4_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "// TODO If the condition is inverted, the object farthest from the specified position is picked instead.\r", + "const inverted = false;\r", + "\r", + "eventsFunctionContext.returnValue = gdjs._collision3DExtension.pickNearestObject(\r", + " eventsFunctionContext.getObjectsLists(\"Object\"),\r", + " eventsFunctionContext.getArgument(\"PositionX\"),\r", + " eventsFunctionContext.getArgument(\"PositionY\"),\r", + " eventsFunctionContext.getArgument(\"PositionZ\"),\r", + " inverted\r", + ");" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "objectList" + }, + { + "description": "X position", + "name": "PositionX", + "type": "expression" + }, + { + "description": "Y position", + "name": "PositionY", + "type": "expression" + }, + { + "description": "Z position", + "name": "PositionZ", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Check the collision between two objects using their collision masks. Object rotation around X and Y axes are ignored.", + "fullName": "Collision in 3D", + "functionType": "Condition", + "group": "Collision", + "name": "AreInCollision", + "sentence": "_PARAM1_ is in collision with _PARAM3_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "// TODO If the condition is inverted, the object farthest from the specified position is picked instead.\r", + "const inverted = false;\r", + "\r", + "eventsFunctionContext.returnValue = gdjs._collision3DExtension.pickObjectsInCollision(\r", + " eventsFunctionContext.getObjectsLists(\"Object\"),\r", + " eventsFunctionContext.getObjectsLists(\"OtherObject\"),\r", + " eventsFunctionContext.getArgument(\"IgnoreEdges\"),\r", + " inverted\r", + ");" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + }, + { + "description": "Other object", + "name": "OtherObject", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "OtherObjectCapability", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + }, + { + "description": "Ignore objects that are touching each other on their edges, but are not overlapping (default: no)", + "name": "IgnoreEdges", + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "Move an object away from another using their collision masks. Object rotation around X and Y axes are ignored.\nBe sure to call this action on a reasonable number of objects to avoid slowing down the game.", + "fullName": "Separate objects in 3D", + "functionType": "Action", + "group": "Position", + "name": "SeparateFromObjects", + "sentence": "Move _PARAM1_ away from _PARAM3_ (only _PARAM1_ will move)", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const otherObjects = eventsFunctionContext.getObjects(\"OtherObject\");\r", + "\r", + "for (const object of objects) {\r", + " gdjs._collision3DExtension.separateFromObjects(\r", + " object,\r", + " otherObjects,\r", + " );\r", + "}" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + }, + { + "description": "Objects (won't move)", + "name": "OtherObject", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "OtherObject3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Rotate the object to make it faces a position. The object default orientation must be toward the right in top-down view.", + "fullName": "Look at position", + "functionType": "Action", + "group": "Angle", + "name": "LookAtPosition", + "sentence": "Rotate _PARAM1_ to look at _PARAM3_, _PARAM4_, _PARAM5_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const capability3DBehaviorName = eventsFunctionContext.getBehaviorName(\"Object3D\");\r", + "const targetX = eventsFunctionContext.getArgument(\"TargetX\");\r", + "const targetY = eventsFunctionContext.getArgument(\"TargetY\");\r", + "const targetZ = eventsFunctionContext.getArgument(\"TargetZ\");\r", + "\r", + "\r", + "for (const object of objects) {\r", + " const threeObject = object.get3DRendererObject();\r", + "\r", + " // Ensure custom object position is up to date.\r", + " if (object.getRenderer && object.getRenderer().ensureUpToDate) {\r", + " object.getRenderer().ensureUpToDate();\r", + " }\r", + "\r", + " const threeScene = runtimeScene.getLayer(object.getLayer()).getRenderer().getThreeScene();\r", + " threeScene.scale.y = 1;\r", + " threeObject.up.set(0, 0, 1);\r", + " threeObject.lookAt(targetX, targetY, targetZ);\r", + " threeScene.scale.y = -1;\r", + "\r", + " // TODO This only works for particles because they are Z+ by default.\r", + " const rotationX = gdjs.toDegrees(threeObject.rotation.x);\r", + " const rotationY = gdjs.toDegrees(threeObject.rotation.y);\r", + " const rotationZ = gdjs.toDegrees(threeObject.rotation.z);\r", + "\r", + " /** @type {gdjs.Base3DBehavior} */\r", + " const capability3D = object.getBehavior(capability3DBehaviorName);\r", + " capability3D.setRotationX(rotationX);\r", + " capability3D.setRotationY(rotationY);\r", + " object.setAngle(rotationZ);\r", + " //console.log(\"Rotation\", rotationX, rotationY, rotationZ);\r", + "}\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + }, + { + "description": "Target X", + "name": "TargetX", + "type": "expression" + }, + { + "description": "Target Y", + "name": "TargetY", + "type": "expression" + }, + { + "description": "Target Z", + "name": "TargetZ", + "type": "expression" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "DefineHelperClasses" + }, + { + "functionName": "onFirstSceneLoaded" + }, + { + "folderName": "Position", + "children": [ + { + "functionName": "AreWithinDistance" + }, + { + "functionName": "Distance" + }, + { + "functionName": "SqDistance" + }, + { + "functionName": "DistanceToPosition" + }, + { + "functionName": "SqDistanceToPosition" + }, + { + "functionName": "SeparateFromObjects" + } + ] + }, + { + "folderName": "Objects", + "children": [ + { + "functionName": "PickNearest" + } + ] + }, + { + "folderName": "Collision", + "children": [ + { + "functionName": "AreInCollision" + } + ] + }, + { + "folderName": "Angle", + "children": [ + { + "functionName": "LookAtPosition" + } + ] + } + ] + }, + "eventsBasedBehaviors": [], + "eventsBasedObjects": [] + }, + { + "author": "Bouh", + "category": "Input", + "dimension": "", + "extensionNamespace": "", + "fullName": "Gamepads (controllers)", + "gdevelopVersion": ">=5.5.222", + "helpPath": "/all-features/gamepad", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0ibWRpLWdhbWVwYWQtdmFyaWFudC1vdXRsaW5lIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTYsOUg4VjExSDEwVjEzSDhWMTVINlYxM0g0VjExSDZWOU0xOC41LDlBMS41LDEuNSAwIDAsMSAyMCwxMC41QTEuNSwxLjUgMCAwLDEgMTguNSwxMkExLjUsMS41IDAgMCwxIDE3LDEwLjVBMS41LDEuNSAwIDAsMSAxOC41LDlNMTUuNSwxMkExLjUsMS41IDAgMCwxIDE3LDEzLjVBMS41LDEuNSAwIDAsMSAxNS41LDE1QTEuNSwxLjUgMCAwLDEgMTQsMTMuNUExLjUsMS41IDAgMCwxIDE1LjUsMTJNMTcsNUE3LDcgMCAwLDEgMjQsMTJBNyw3IDAgMCwxIDE3LDE5QzE1LjA0LDE5IDEzLjI3LDE4LjIgMTIsMTYuOUMxMC43MywxOC4yIDguOTYsMTkgNywxOUE3LDcgMCAwLDEgMCwxMkE3LDcgMCAwLDEgNyw1SDE3TTcsN0E1LDUgMCAwLDAgMiwxMkE1LDUgMCAwLDAgNywxN0M4LjY0LDE3IDEwLjA5LDE2LjIxIDExLDE1SDEzQzEzLjkxLDE2LjIxIDE1LjM2LDE3IDE3LDE3QTUsNSAwIDAsMCAyMiwxMkE1LDUgMCAwLDAgMTcsN0g3WiIgLz48L3N2Zz4=", + "name": "Gamepads", + "previewIconUrl": "https://resources.gdevelop-app.com/assets/Icons/gamepad-variant-outline.svg", + "shortDescription": "Add support for gamepads (or other controllers) to your game, giving access to information such as button presses, axis positions, trigger pressure, etc...", + "version": "0.9.0", + "description": [ + "Add support for gamepads (or other physical controllers).", + "", + "It gives access to:", + "- button presses,", + "- axis positions and force,", + "- trigger pressure,", + "- configurable deadzone,", + "- vibration,", + "- automatic \"gamepad mapper\" behaviors for 2D and 3D movement behaviors (platformer characters, top-down movement, 3D character etc...). Add one of these to the object with the movement behavior (i.e: the player most of the time) and the behavior will then be controlled automatically by the gamepad (it works by reading the gamepad state and simulating controls). No need for additional events to make it work once the behaviors are set up.", + "", + "The Bomberman-like example handles 4 players with gamepads ([open the project online](https://editor.gdevelop.io/?project=example://goose-bomberman))." + ], + "origin": { + "identifier": "Gamepads", + "name": "gdevelop-extension-store" + }, + "tags": [ + "controllers", + "gamepads", + "joysticks", + "axis", + "xbox", + "ps4", + "platformer", + "platform", + "top-down" + ], + "authorIds": [ + "2OwwM8ToR9dx9RJ2sAKTcrLmCB92", + "taRwmWxwAFYFL9yyBwB3cwBw0BO2", + "mnImQKdn8nQxwzkS5D6a1JB27V23", + "IWykYNRvhCZBN3vEgKEbBPOR3Oc2" + ], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [ + { + "name": "Buttons", + "type": "structure", + "children": [ + { + "name": "A or Cross", + "type": "string", + "value": "A" + }, + { + "name": "B or Circle", + "type": "string", + "value": "B" + }, + { + "name": "LB or L1", + "type": "string", + "value": "LB" + }, + { + "name": "LT or L2", + "type": "string", + "value": "LT" + }, + { + "name": "RB or R1", + "type": "string", + "value": "RB" + }, + { + "name": "RT or R2", + "type": "string", + "value": "RT" + }, + { + "name": "X or Square", + "type": "string", + "value": "X" + }, + { + "name": "Y or Triangle", + "type": "string", + "value": "Y" + } + ] + } + ], + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onFirstSceneLoaded", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "if (gdjs._extensionController) {\r", + " return;\r", + "}\r", + "\r", + "/**\r", + " * Associate controller button ids to button names\r", + " */\r", + "const controllerButtonNames = {\r", + " \"XBOX\": {\r", + " 0: \"A\",\r", + " 1: \"B\",\r", + " 2: \"X\",\r", + " 3: \"Y\",\r", + " 4: \"LB\",\r", + " 5: \"RB\",\r", + " 6: \"LT\",\r", + " 7: \"RT\",\r", + " 8: \"BACK\",\r", + " 9: \"START\",\r", + " 10: \"CLICK_STICK_LEFT\",\r", + " 11: \"CLICK_STICK_RIGHT\",\r", + " 12: \"UP\",\r", + " 13: \"DOWN\",\r", + " 14: \"LEFT\",\r", + " 15: \"RIGHT\",\r", + " 16: \"NONE\",\r", + " 17: \"NONE\"\r", + " },\r", + " \"PS4\": {\r", + " 0: \"CROSS\",\r", + " 1: \"CIRCLE\",\r", + " 2: \"SQUARE\",\r", + " 3: \"TRIANGLE\",\r", + " 4: \"L1\",\r", + " 5: \"R1\",\r", + " 6: \"L2\",\r", + " 7: \"R2\",\r", + " 8: \"SHARE\",\r", + " 9: \"OPTIONS\",\r", + " 10: \"CLICK_STICK_LEFT\",\r", + " 11: \"CLICK_STICK_RIGHT\",\r", + " 12: \"UP\",\r", + " 13: \"DOWN\",\r", + " 14: \"LEFT\",\r", + " 15: \"RIGHT\",\r", + " 16: \"PS_BUTTON\",\r", + " 17: \"CLICK_TOUCHPAD\"\r", + " }\r", + "};\r", + "\r", + "/**\r", + " * @param {number} playerId\r", + " */\r", + "function getGamepad(playerId) {\r", + " /** @type {Gamepad[]} */\r", + " const gamepads = navigator.getGamepads ? navigator.getGamepads() : [];\r", + " return gamepads[playerId];\r", + "}\r", + "\r", + "/** @type {{[playerId: number]: Player}} */\r", + "const players = {};\r", + "\r", + "/**\r", + " * @param {number} playerId\r", + " */\r", + "function getPlayer(playerId) {\r", + " let player = players[playerId];\r", + " if (!player) {\r", + " player = new Player(playerId);\r", + " players[playerId] = player;\r", + " }\r", + " return player;\r", + "}\r", + "\r", + "class Player {\r", + " /** @type {number} */\r", + " playerId;\r", + " mapping = 'DEFAULT';\r", + " lastButtonUsed = -1;\r", + " deadzone = 0.2;\r", + " /** @type {{[buttonId: number]: ButtonState}} */\r", + " buttonStates = {};\r", + " rumble = { elapsedTime: 0, duration: 0, weakMagnitude: 0, strongMagnitude: 0 };\r", + "\r", + " /**\r", + " * @param {number} playerId\r", + " */\r", + " constructor(playerId) {\r", + " this.playerId = playerId;\r", + " }\r", + "\r", + " /**\r", + " * @param {number} buttonId\r", + " */\r", + " getButtonState(buttonId) {\r", + " let buttonState = this.buttonStates[buttonId];\r", + " if (!buttonState) {\r", + " buttonState = new ButtonState();\r", + " this.buttonStates[buttonId] = buttonState;\r", + " }\r", + " return buttonState;\r", + " }\r", + "\r", + " /**\r", + " * @param {number} buttonId\r", + " */\r", + " isButtonPressed(buttonId) {\r", + " return this.getButtonState(buttonId).isPressed;\r", + " }\r", + "\r", + " /**\r", + " * @param {number} buttonId\r", + " */\r", + " isButtonJustPressed(buttonId) {\r", + " return this.getButtonState(buttonId).isJustPressed();\r", + " }\r", + "\r", + " /**\r", + " * @param {number} buttonId\r", + " */\r", + " isButtonReleased(buttonId) {\r", + " return this.getButtonState(buttonId).isReleased();\r", + " }\r", + "\r", + " isAnyButtonReleased() {\r", + " for (const buttonId in this.buttonStates) {\r", + " const buttonState = this.buttonStates[buttonId];\r", + " if (buttonState.isReleased()) {\r", + " return true;\r", + " }\r", + " }\r", + " return false;\r", + " }\r", + "\r", + " isAnyButtonPressed() {\r", + " for (const buttonId in this.buttonStates) {\r", + " const buttonState = this.buttonStates[buttonId];\r", + " if (buttonState.isPressed) {\r", + " return true;\r", + " }\r", + " }\r", + " return false;\r", + " }\r", + "}\r", + "\r", + "class ButtonState {\r", + " wasPressed = false;\r", + " isPressed = false;\r", + "\r", + " isReleased() {\r", + " return this.wasPressed && !this.isPressed;\r", + " }\r", + "\r", + " isJustPressed() {\r", + " return !this.wasPressed && this.isPressed;\r", + " }\r", + "}\r", + "\r", + "// Async tasks are run before everything.\r", + "// This is a hack to make sure that button states are updated\r", + "// before mapping behavior events.\r", + "const frameBeginningTask = new class extends gdjs.AsyncTask {\r", + " update() {\r", + " /** @type {Gamepad[]} */\r", + " const gamepads = navigator.getGamepads ? navigator.getGamepads() : [];\r", + " for (let playerId = 0; playerId < gamepads.length; playerId++) {\r", + " const gamepad = gamepads[playerId];\r", + " if (gamepad == null) {\r", + " // The gamepad is not connected.\r", + " continue;\r", + " }\r", + " const player = getPlayer(playerId);\r", + "\r", + " for (let buttonId = 0; buttonId < Object.keys(gamepad.buttons).length; buttonId++) {\r", + " const buttonState = player.getButtonState(buttonId);\r", + " buttonState.wasPressed = buttonState.isPressed;\r", + " buttonState.isPressed = gamepad.buttons[buttonId].pressed;\r", + " if (buttonState.isJustPressed()) {\r", + " player.lastButtonUsed = buttonId;\r", + " }\r", + " }\r", + " }\r", + " return false;\r", + " }\r", + "}();\r", + "\r", + "function onScenePostEvents() {\r", + " /** @type {Gamepad[]} */\r", + " const gamepads = navigator.getGamepads ? navigator.getGamepads() : [];\r", + " for (let playerId = 0; playerId < gamepads.length; playerId++) {\r", + " let gamepad = gamepads[playerId];\r", + " if (gamepad == null) {\r", + " // The gamepad is not connected.\r", + " continue;\r", + " }\r", + " const player = getPlayer(playerId);\r", + " const rumble = player.rumble;\r", + " rumble.elapsedTime += runtimeScene.getElapsedTime(runtimeScene) / 1000;\r", + " if (rumble.duration - rumble.elapsedTime <= 0 &&\r", + " (rumble.weakMagnitude || rumble.strongMagnitude)\r", + " ) {\r", + " rumble.weakMagnitude = 0;\r", + " rumble.strongMagnitude = 0;\r", + " }\r", + " }\r", + "}\r", + "\r", + "/**\r", + " * @param {string} type\r", + " * @param {number} buttonId\r", + " */\r", + "function getInputString(type, buttonId) {\r", + " if (!controllerButtonNames[type]) {\r", + " return \"UNKNOWN_BUTTON\";\r", + " }\r", + " return controllerButtonNames[type][buttonId];\r", + "}\r", + "\r", + "function getButtonId(buttonName) {\r", + " switch (buttonName) {\r", + " case 'A':\r", + " case 'CROSS':\r", + " return 0;\r", + " case 'B':\r", + " case 'CIRCLE':\r", + " return 1;\r", + " case 'X':\r", + " case 'SQUARE':\r", + " return 2;\r", + " case 'Y':\r", + " case 'TRIANGLE':\r", + " return 3;\r", + " case 'LB':\r", + " case 'L1':\r", + " return 4;\r", + " case 'RB':\r", + " case 'R1':\r", + " return 5;\r", + " case 'LT':\r", + " case 'L2':\r", + " return 6;\r", + " case 'RT':\r", + " case 'R2':\r", + " return 7;\r", + " case 'UP':\r", + " return 12;\r", + " case 'DOWN':\r", + " return 13;\r", + " case 'LEFT':\r", + " return 14;\r", + " case 'RIGHT':\r", + " return 15;\r", + " case 'BACK':\r", + " case 'SHARE':\r", + " return 8;\r", + " case 'START':\r", + " case 'OPTIONS':\r", + " return 9;\r", + " case 'CLICK_STICK_LEFT':\r", + " return 10;\r", + " case 'CLICK_STICK_RIGHT':\r", + " return 11;\r", + " //PS4\r", + " case 'PS_BUTTON':\r", + " return 16;\r", + " case 'CLICK_TOUCHPAD':\r", + " return 17;\r", + " default:\r", + " console.error('The gamepad button: ' + buttonName + ' is not valid.');\r", + " return null;\r", + " }\r", + "}\r", + "\r", + "/**\r", + " * @param {number} playerId\r", + " * @param {string} directionName\r", + " * @param {number} axisValueX\r", + " * @param {number} axisValueY\r", + " */\r", + "function isAxisPushed(playerId, directionName, axisValueX, axisValueY) {\r", + " switch (directionName) {\r", + " case 'LEFT':\r", + " return getNormalizedAxisValue(axisValueX, playerId) < 0;\r", + " case 'RIGHT':\r", + " return getNormalizedAxisValue(axisValueX, playerId) > 0;\r", + " case 'UP':\r", + " return getNormalizedAxisValue(axisValueY, playerId) < 0;\r", + " case 'DOWN':\r", + " return getNormalizedAxisValue(axisValueY, playerId) > 0;\r", + " case 'ANY':\r", + " return getNormalizedAxisValue(axisValueX, playerId) < 0\r", + " || getNormalizedAxisValue(axisValueX, playerId) > 0\r", + " || getNormalizedAxisValue(axisValueY, playerId) < 0\r", + " || getNormalizedAxisValue(axisValueY, playerId) > 0\r", + " default:\r", + " console.error('The value stick direction is not valid.');\r", + " return false;\r", + " }\r", + "}\r", + "\r", + "/**\r", + " * @param {number} deltaX\r", + " * @param {number} deltaY\r", + " */\r", + "function axisToAngle(deltaX, deltaY) {\r", + " const rad = Math.atan2(deltaY, deltaX);\r", + " const deg = rad * (180 / Math.PI);\r", + " return deg;\r", + "}\r", + "\r", + "/**\r", + " * @param {{id: string}} gamepad\r", + " */\r", + "function isXbox(gamepad) {\r", + " return (gamepad ? (\r", + " gamepad.id.toUpperCase().indexOf(\"XBOX\") !== -1\r", + " // \"XINPUT\" cannot be used to check if it is a xbox controller is just a generic\r", + " // name reported in Firefox corresponding to the driver being used by the controller\r", + " // https://gamefaqs.gamespot.com/boards/916373-pc/73341312?page=1\r", + " ) : false);\r", + "}\r", + "\r", + "/**\r", + " * Returns the new value taking into account the dead zone for the player_ID given\r", + " * @param {number} value\r", + " * @param {number} playerID\r", + " */\r", + "function getNormalizedAxisValue(value, playerID) {\r", + " // gdjs._extensionController = gdjs._extensionController || { deadzone: 0.2 };\r", + "\r", + " // Anything smaller than this is assumed to be 0,0\r", + " const deadzone = getPlayer(playerID).deadzone;\r", + "\r", + " if (Math.abs(value) < deadzone) {\r", + " return 0;\r", + " } else {\r", + " // We're outside the dead zone, but we'd like to smooth\r", + " // this value out so it still runs nicely between 0..1.\r", + " // That is, we don't want it to jump suddenly from 0 to\r", + " // deadzone.\r", + "\r", + " // Remap value from\r", + " // deadzone..1 to 0..(1-deadzone)\r", + " // or from\r", + " // -1..-deadzone to -(1-deadzone)..0\r", + " value = value - Math.sign(value) * deadzone;\r", + "\r", + " // Remap value from\r", + " // 0..(1-deadzone) to 0..1\r", + " // or from\r", + " // -(1-deadzone)..0 to -1..0\r", + " return value / (1 - deadzone);\r", + " }\r", + "}\r", + "\r", + "gdjs._extensionController = {\r", + " getPlayer,\r", + " controllerButtonNames,\r", + " getInputString,\r", + " getButtonId,\r", + " axisToAngle,\r", + " isXbox,\r", + " getNormalizedAxisValue,\r", + " isAxisPushed,\r", + " getGamepad,\r", + " onScenePostEvents,\r", + " frameBeginningTask,\r", + "}" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onSceneLoaded", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "// Async tasks are run before everything.\r", + "// This is a hack to make sure that button states are updated\r", + "// before mapping behavior events.\r", + "runtimeScene.getAsyncTasksManager().addTask(gdjs._extensionController.frameBeginningTask);" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onScenePostEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "gdjs._extensionController.onScenePostEvents();", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "fullName": "Accelerated speed", + "functionType": "Expression", + "name": "AcceleratedSpeed", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AcceleratedSpeed", + "=", + "CurrentSpeed" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "TargetedSpeed", + "<", + "0" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Reduce the speed to match the stick force." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentSpeed", + "<", + "TargetedSpeed" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AcceleratedSpeed", + "=", + "min(TargetedSpeed, CurrentSpeed + Acceleration * TimeDelta())" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentSpeed", + ">", + "TargetedSpeed" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentSpeed", + "<", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AcceleratedSpeed", + "-", + "Acceleration * TimeDelta()" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Turn back at least as fast as it would stop." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentSpeed", + ">=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AcceleratedSpeed", + "=", + "max(TargetedSpeed, CurrentSpeed - max(Acceleration , Deceleration) * TimeDelta())" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "TargetedSpeed", + ">", + "0" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Reduce the speed to match the stick force." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentSpeed", + ">", + "TargetedSpeed" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AcceleratedSpeed", + "=", + "max(TargetedSpeed, CurrentSpeed - Acceleration * TimeDelta())" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentSpeed", + "<", + "TargetedSpeed" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentSpeed", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AcceleratedSpeed", + "+", + "Acceleration * TimeDelta()" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Turn back at least as fast as it would stop." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentSpeed", + "<=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AcceleratedSpeed", + "=", + "min(TargetedSpeed, CurrentSpeed + max(Acceleration , Deceleration) * TimeDelta())" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "TargetedSpeed", + "=", + "0" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentSpeed", + "<", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AcceleratedSpeed", + "=", + "min(0, CurrentSpeed + Acceleration * TimeDelta())" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CurrentSpeed", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AcceleratedSpeed", + "=", + "max(0, CurrentSpeed - Acceleration * TimeDelta())" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "clamp(AcceleratedSpeed, -SpeedMax, SpeedMax)" + ] + } + ] + } + ], + "variables": [ + { + "name": "AcceleratedSpeed", + "type": "number", + "value": 0 + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Current speed", + "name": "CurrentSpeed", + "type": "expression" + }, + { + "description": "Targeted speed", + "name": "TargetedSpeed", + "type": "expression" + }, + { + "description": "Max speed", + "name": "SpeedMax", + "type": "expression" + }, + { + "description": "Acceleration", + "name": "Acceleration", + "type": "expression" + }, + { + "description": "Deceleration", + "name": "Deceleration", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Get the value of the pressure on a gamepad trigger.", + "fullName": "Pressure on a gamepad trigger", + "functionType": "Expression", + "name": "TriggerPressure", + "sentence": "Player _PARAM1_ push axis _PARAM2_ to _PARAM3_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;\r", + "const trigger = eventsFunctionContext.getArgument(\"Trigger\").toUpperCase();\r", + "\r", + "if (trigger != \"LT\" && trigger != \"RT\" && trigger != \"L2\" && trigger != \"R2\") {\r", + " console.error('Parameter trigger is not valid in expression: \"Pressure on a gamepad trigger\"');\r", + " return;\r", + "}\r", + "/** @type {Gamepad} */\r", + "const gamepad = gdjs._extensionController.getGamepad(playerId);\r", + "if (!gamepad) {\r", + " // The gamepad is not connected.\r", + " return;\r", + "}\r", + "switch (trigger) {\r", + " case 'LT':\r", + " case 'L2':\r", + " eventsFunctionContext.returnValue = gamepad.buttons[6].value;\r", + " break;\r", + "\r", + " case 'RT':\r", + " case 'R2':\r", + " eventsFunctionContext.returnValue = gamepad.buttons[7].value;\r", + " break;\r", + "\r", + " default:\r", + " eventsFunctionContext.returnValue = -1;\r", + " break;\r", + "}" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + }, + { + "description": "Trigger button", + "name": "Trigger", + "supplementaryInformation": "[\"LT\",\"RT\",\"L2\",\"R2\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "the force of gamepad stick (from 0 to 1).", + "fullName": "Stick force", + "functionType": "ExpressionAndCondition", + "name": "StickForce", + "sentence": "the gamepad _PARAM1_ _PARAM2_ stick force", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const { getNormalizedAxisValue } = gdjs._extensionController;\r", + "\r", + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;\r", + "const stick = eventsFunctionContext.getArgument(\"Stick\").toUpperCase();\r", + "\r", + "if (stick !== \"LEFT\" && stick !== \"RIGHT\") {\r", + " console.error('Parameter stick is not valid in expression: \"Value of a stick force\"');\r", + " return;\r", + "}\r", + "/** @type {Gamepad} */\r", + "const gamepad = gdjs._extensionController.getGamepad(playerId);\r", + "if (!gamepad) {\r", + " // The gamepad is not connected.\r", + " return;\r", + "}\r", + "const axisValueX = stick === 'RIGHT' ? gamepad.axes[2] : gamepad.axes[0];\r", + "const axisValueY = stick === 'RIGHT' ? gamepad.axes[3] : gamepad.axes[1];\r", + "\r", + "eventsFunctionContext.returnValue = gdjs.evtTools.common.clamp(\r", + " Math.abs(getNormalizedAxisValue(axisValueX, playerId)) +\r", + " Math.abs(getNormalizedAxisValue(axisValueY, playerId)), 0, 1);\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + }, + { + "description": "Stick: \"Left\" or \"Right\"", + "name": "Stick", + "supplementaryInformation": "[\"Left\",\"Right\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Get the rotation value of a gamepad stick.\nIf the deadzone value is high, the angle value is rounded to main axes, left, left, up, down.\nAn zero deadzone value give a total freedom on the angle value.", + "fullName": "Value of a stick rotation (deprecated)", + "functionType": "Expression", + "name": "StickRotationValue", + "private": true, + "sentence": "Player _PARAM1_ push axis _PARAM2_ to _PARAM3_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Gamepads::StickAngle(PlayerId, Stick)" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + }, + { + "description": "Stick: \"Left\" or \"Right\"", + "name": "Stick", + "supplementaryInformation": "[\"Left\",\"Right\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Return the angle of a gamepad stick.\nIf the deadzone value is high, the angle value is rounded to main axes, left, left, up, down.\nAn zero deadzone value give a total freedom on the angle value.", + "fullName": "Stick angle", + "functionType": "Expression", + "name": "StickAngle", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const { getNormalizedAxisValue } = gdjs._extensionController;\r", + "\r", + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;\r", + "const stick = eventsFunctionContext.getArgument(\"Stick\").toUpperCase();\r", + "\r", + "if (stick !== \"LEFT\" && stick !== \"RIGHT\") {\r", + " console.error('Parameter stick is not valid in expression: \"Value of a stick rotation\"');\r", + " return;\r", + "}\r", + "/** @type {Gamepad} */\r", + "const gamepad = gdjs._extensionController.getGamepad(playerId);\r", + "if (!gamepad) {\r", + " // The gamepad is not connected.\r", + " return;\r", + "}\r", + "const axisValueX = stick === 'RIGHT' ? gamepad.axes[2] : gamepad.axes[0];\r", + "const axisValueY = stick === 'RIGHT' ? gamepad.axes[3] : gamepad.axes[1];\r", + "\r", + "eventsFunctionContext.returnValue = gdjs._extensionController.axisToAngle(\r", + " getNormalizedAxisValue(axisValueX, playerId),\r", + " getNormalizedAxisValue(axisValueY, playerId));" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + }, + { + "description": "Stick: \"Left\" or \"Right\"", + "name": "Stick", + "supplementaryInformation": "[\"Left\",\"Right\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Get the value of axis of a gamepad stick.", + "fullName": "Value of a gamepad axis (deprecated)", + "functionType": "Expression", + "name": "AxisValue", + "private": true, + "sentence": "Player _PARAM1_ push axis _PARAM2_ to _PARAM3_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;\r", + "const stick = eventsFunctionContext.getArgument(\"stick\").toUpperCase();\r", + "const direction = eventsFunctionContext.getArgument(\"direction\").toUpperCase();\r", + "\r", + "if (stick != \"LEFT\" && stick != \"RIGHT\") {\r", + " console.error('Parameter stick is not valid in expression: \"Value of a gamepad axis\"');\r", + " return;\r", + "}\r", + "if (direction != \"UP\" && direction != \"DOWN\" && direction != \"LEFT\" && direction != \"RIGHT\" && direction != \"HORIZONTAL\" && direction != \"VERTICAL\") {\r", + " console.error('Parameter direction is not valid in expression: \"Value of a gamepad axis\"');\r", + " return;\r", + "}\r", + "/** @type {Gamepad} */\r", + "const gamepad = gdjs._extensionController.getGamepad(playerId);\r", + "if (!gamepad) {\r", + " // The gamepad is not connected.\r", + " return;\r", + "}\r", + "let parameterError = false;\r", + "switch (stick) {\r", + " case 'LEFT':\r", + " switch (direction) {\r", + " case 'LEFT':\r", + " if (gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[0], playerId) < 0) {\r", + " eventsFunctionContext.returnValue = -gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[0], playerId);\r", + " }\r", + " break;\r", + "\r", + " case 'RIGHT':\r", + " if (gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[0], playerId) > 0) {\r", + " eventsFunctionContext.returnValue = gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[0], playerId);\r", + " }\r", + " break;\r", + "\r", + " case 'UP':\r", + " if (gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[1], playerId) < 0) {\r", + " eventsFunctionContext.returnValue = -gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[1], playerId);\r", + " }\r", + " break;\r", + "\r", + " case 'DOWN':\r", + " if (gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[1], playerId) > 0) {\r", + " eventsFunctionContext.returnValue = gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[1], playerId);\r", + " }\r", + " break;\r", + "\r", + " case \"HORIZONTAL\":\r", + " eventsFunctionContext.returnValue = gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[0], playerId);\r", + " break;\r", + "\r", + " case \"VERTICAL\":\r", + " eventsFunctionContext.returnValue = gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[1], playerId);\r", + " break;\r", + "\r", + " default:\r", + " break;\r", + " }\r", + " break;\r", + "\r", + " case 'RIGHT':\r", + " switch (direction) {\r", + " case 'LEFT':\r", + " if (gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[2], playerId) < 0) {\r", + " eventsFunctionContext.returnValue = -gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[2], playerId);\r", + " }\r", + " break;\r", + "\r", + " case 'RIGHT':\r", + " if (gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[2], playerId) > 0) {\r", + " eventsFunctionContext.returnValue = gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[2], playerId);\r", + " }\r", + " break;\r", + "\r", + " case 'UP':\r", + " if (gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[3], playerId) < 0) {\r", + " eventsFunctionContext.returnValue = -gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[3], playerId);\r", + " }\r", + " break;\r", + "\r", + " case 'DOWN':\r", + " if (gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[3], playerId) > 0) {\r", + " eventsFunctionContext.returnValue = gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[3], playerId);\r", + " }\r", + " break;\r", + "\r", + " case \"HORIZONTAL\":\r", + " eventsFunctionContext.returnValue = gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[2], playerId);\r", + " break;\r", + "\r", + " case \"VERTICAL\":\r", + " eventsFunctionContext.returnValue = gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[3], playerId);\r", + " break;\r", + "\r", + " default:\r", + " break;\r", + " }\r", + " break;\r", + "\r", + " default:\r", + " break;\r", + "}\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + }, + { + "description": "Stick: \"Left\" or \"Right\"", + "name": "stick", + "supplementaryInformation": "[\"Left\",\"Right\"]", + "type": "stringWithSelector" + }, + { + "description": "Direction", + "name": "direction", + "supplementaryInformation": "[\"Up\",\"Down\",\"Left\",\"Right\",\"Horizontal\",\"Vertical\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Return the gamepad stick force on X axis (from -1 at the left to 1 at the right).", + "fullName": "Stick X force", + "functionType": "Expression", + "name": "StickForceX", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const playerId = eventsFunctionContext.getArgument(\"Gamepad\") - 1;\r", + "const stick = eventsFunctionContext.getArgument(\"Stick\").toLowerCase();\r", + "\r", + "if (stick != \"left\" && stick != \"right\") {\r", + " console.error('Parameter stick is not valid in expression: \"Value of a gamepad axis\"');\r", + " return;\r", + "}\r", + "/** @type {Gamepad} */\r", + "const gamepad = gdjs._extensionController.getGamepad(playerId);\r", + "if (!gamepad) {\r", + " // The gamepad is not connected.\r", + " return;\r", + "}\r", + "const axisIndex = stick === 'right' ? 2 : 0;\r", + "eventsFunctionContext.returnValue = gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[axisIndex], playerId);\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "Gamepad", + "type": "expression" + }, + { + "description": "Stick: \"Left\" or \"Right\"", + "name": "Stick", + "supplementaryInformation": "[\"Left\",\"Right\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Return the gamepad stick force on Y axis (from -1 at the top to 1 at the bottom).", + "fullName": "Stick Y force", + "functionType": "Expression", + "name": "StickForceY", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const playerId = eventsFunctionContext.getArgument(\"Gamepad\") - 1;\r", + "const stick = eventsFunctionContext.getArgument(\"Stick\").toLowerCase();\r", + "\r", + "if (stick != \"left\" && stick != \"right\") {\r", + " console.error('Parameter stick is not valid in expression: \"Value of a gamepad axis\"');\r", + " return;\r", + "}\r", + "/** @type {Gamepad} */\r", + "const gamepad = gdjs._extensionController.getGamepad(playerId);\r", + "if (!gamepad) {\r", + " // The gamepad is not connected.\r", + " return;\r", + "}\r", + "const axisIndex = stick === 'right' ? 3 : 1;\r", + "eventsFunctionContext.returnValue = gdjs._extensionController.getNormalizedAxisValue(gamepad.axes[axisIndex], playerId);\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "Gamepad", + "type": "expression" + }, + { + "description": "Stick: \"Left\" or \"Right\"", + "name": "Stick", + "supplementaryInformation": "[\"Left\",\"Right\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Test if a button is released on a gamepad. Buttons can be:\n* Xbox: \"A\", \"B\", \"X\", \"Y\", \"LB\", \"RB\", \"LT\", \"RT\", \"BACK\", \"START\",\n* PS4: \"CROSS\", \"SQUARE\", \"CIRCLE\", \"TRIANGLE\", \"L1\", \"L2\", \"R1\", \"R2\", \"SHARE\", \"OPTIONS\", \"PS_BUTTON\", \"CLICK_TOUCHPAD\",\n* Other: \"UP\", \"DOWN\", \"LEFT\", \"RIGHT\", \"CLICK_STICK_LEFT\", \"CLICK_STICK_RIGHT\".", + "fullName": "Gamepad button released", + "functionType": "Condition", + "name": "C_Button_released", + "sentence": "Button _PARAM2_ of gamepad _PARAM1_ is released", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;\r", + "const button = eventsFunctionContext.getArgument(\"Button\").toUpperCase();\r", + "\r", + "let buttonId = gdjs._extensionController.getButtonId(button);\r", + "if (buttonId === null) {\r", + " return;\r", + "}\r", + "const player = gdjs._extensionController.getPlayer(playerId)\r", + "eventsFunctionContext.returnValue = player.isButtonReleased(buttonId);" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + }, + { + "description": "Name of the button", + "name": "Button", + "supplementaryInformation": "[\"A\",\"Cross\",\"B\",\"Circle\",\"X\",\"Square\",\"Y\",\"Triangle\",\"LB\",\"L1\",\"RB\",\"R1\",\"LT\",\"L2\",\"RT\",\"R2\",\"Up\",\"Down\",\"Left\",\"Right\",\"Back\",\"Share\",\"Start\",\"Options\",\"Click_Stick_Left\",\"Click_Stick_Right\",\"PS_Button\",\"Click_Touchpad\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Check if a button was just pressed on a gamepad. Buttons can be:\n* Xbox: \"A\", \"B\", \"X\", \"Y\", \"LB\", \"RB\", \"LT\", \"RT\", \"BACK\", \"START\",\n* PS4: \"CROSS\", \"SQUARE\", \"CIRCLE\", \"TRIANGLE\", \"L1\", \"L2\", \"R1\", \"R2\", \"SHARE\", \"OPTIONS\", \"PS_BUTTON\", \"CLICK_TOUCHPAD\",\n* Other: \"UP\", \"DOWN\", \"LEFT\", \"RIGHT\", \"CLICK_STICK_LEFT\", \"CLICK_STICK_RIGHT\".", + "fullName": "Gamepad button just pressed", + "functionType": "Condition", + "name": "IsButtonJustPressed", + "sentence": "Button _PARAM2_ of gamepad _PARAM1_ was just pressed", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;\r", + "const button = eventsFunctionContext.getArgument(\"Button\").toUpperCase();\r", + "\r", + "let buttonId = gdjs._extensionController.getButtonId(button);\r", + "if (buttonId === null) {\r", + " return;\r", + "}\r", + "const player = gdjs._extensionController.getPlayer(playerId)\r", + "eventsFunctionContext.returnValue = player.isButtonJustPressed(buttonId);" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + }, + { + "description": "Name of the button", + "name": "Button", + "supplementaryInformation": "[\"A\",\"Cross\",\"B\",\"Circle\",\"X\",\"Square\",\"Y\",\"Triangle\",\"LB\",\"L1\",\"RB\",\"R1\",\"LT\",\"L2\",\"RT\",\"R2\",\"Up\",\"Down\",\"Left\",\"Right\",\"Back\",\"Share\",\"Start\",\"Options\",\"Click_Stick_Left\",\"Click_Stick_Right\",\"PS_Button\",\"Click_Touchpad\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Return the index of the last pressed button of a gamepad.", + "fullName": "Last pressed button (id)", + "functionType": "Expression", + "name": "LastButtonID", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;\r", + "eventsFunctionContext.returnValue = gdjs._extensionController.getPlayer(playerId).lastButtonUsed;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Check if any button is pressed on a gamepad.", + "fullName": "Any gamepad button pressed", + "functionType": "Condition", + "name": "C_Any_Button_pressed", + "sentence": "Any button of gamepad _PARAM1_ is pressed", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;\r", + "const player = gdjs._extensionController.getPlayer(playerId)\r", + "eventsFunctionContext.returnValue = player.isAnyButtonPressed();\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Return the last button pressed. \nButtons for Xbox and PS4 can be:\n* Xbox: \"A\", \"B\", \"X\", \"Y\", \"LB\", \"RB\", \"LT\", \"RT\", \"BACK\", \"START\",\n* PS4: \"CROSS\", \"SQUARE\", \"CIRCLE\", \"TRIANGLE\", \"L1\", \"L2\", \"R1\", \"R2\", \"SHARE\", \"OPTIONS\", \"PS_BUTTON\", \"CLICK_TOUCHPAD\",\n* Both: \"UP\", \"DOWN\", \"LEFT\", \"RIGHT\", \"CLICK_STICK_LEFT\", \"CLICK_STICK_RIGHT\".", + "fullName": "Last pressed button (string)", + "functionType": "StringExpression", + "name": "LastButtonString", + "sentence": "Button _PARAM2_ of gamepad _PARAM1_ is pressed", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;\r", + "const controllerType = eventsFunctionContext.getArgument(\"controller_type\").toUpperCase();\r", + "/** @type {Gamepad} */\r", + "const gamepad = gdjs._extensionController.getGamepad(playerId);\r", + "if (!gamepad) {\r", + " // The gamepad is not connected.\r", + " return;\r", + "}\r", + "const lastButtonUsedID = gdjs._extensionController.getPlayer(playerId).lastButtonUsed;\r", + "eventsFunctionContext.returnValue = gdjs._extensionController.getInputString(controllerType, lastButtonUsedID);\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "string" + }, + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + }, + { + "description": "Controller type", + "name": "controller_type", + "supplementaryInformation": "[\"Xbox\",\"PS4\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Return the number of gamepads.", + "fullName": "Gamepad count", + "functionType": "Expression", + "name": "GamepadCount", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const gamepads = navigator.getGamepads ? navigator.getGamepads() : [];\r", + "let lastGamepadIndex = -1;\r", + "for (let playerId = 0; playerId < gamepads.length; playerId++) {\r", + " // Gamepads can be disconnected and become null\r", + " if (gamepads[playerId]) {\r", + " lastGamepadIndex = playerId\r", + " }\r", + "}\r", + "eventsFunctionContext.returnValue = lastGamepadIndex + 1;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [], + "objectGroups": [] + }, + { + "description": "Check if a button is pressed on a gamepad. \nButtons can be:\n* Xbox: \"A\", \"B\", \"X\", \"Y\", \"LB\", \"RB\", \"LT\", \"RT\", \"BACK\", \"START\",\n* PS4: \"CROSS\", \"SQUARE\", \"CIRCLE\", \"TRIANGLE\", \"L1\", \"L2\", \"R1\", \"R2\", \"SHARE\", \"OPTIONS\", \"PS_BUTTON\", \"CLICK_TOUCHPAD\",\n* Other: \"UP\", \"DOWN\", \"LEFT\", \"RIGHT\", \"CLICK_STICK_LEFT\", \"CLICK_STICK_RIGHT\".", + "fullName": "Gamepad button pressed", + "functionType": "Condition", + "name": "C_Button_pressed", + "sentence": "Button _PARAM2_ of gamepad _PARAM1_ is pressed", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;\r", + "const button = eventsFunctionContext.getArgument(\"button\").toUpperCase();\r", + "\r", + "const buttonId = gdjs._extensionController.getButtonId(button);\r", + "if (buttonId === null) {\r", + " return;\r", + "}\r", + "const player = gdjs._extensionController.getPlayer(playerId)\r", + "eventsFunctionContext.returnValue = player.isButtonPressed(buttonId);\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + }, + { + "description": "Name of the button", + "name": "button", + "supplementaryInformation": "[\"A\",\"Cross\",\"B\",\"Circle\",\"X\",\"Square\",\"Y\",\"Triangle\",\"LB\",\"L1\",\"RB\",\"R1\",\"LT\",\"L2\",\"RT\",\"R2\",\"Up\",\"Down\",\"Left\",\"Right\",\"Back\",\"Share\",\"Start\",\"Options\",\"Click_Stick_Left\",\"Click_Stick_Right\",\"PS_Button\",\"Click_Touchpad\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Return the value of the deadzone applied to a gamepad sticks, between 0 and 1.", + "fullName": "Gamepad deadzone for sticks", + "functionType": "Expression", + "name": "Deadzone", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;\r", + "eventsFunctionContext.returnValue = gdjs._extensionController.getPlayer(playerId).deadzone;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Set the deadzone for sticks of the gamepad. The deadzone is an area for which movement on sticks won't be taken into account (instead, the stick will be considered as not moved). Deadzone is between 0 and 1, and is by default 0.2.", + "fullName": "Set gamepad deadzone for sticks", + "functionType": "Action", + "name": "A_Set_deadzone", + "sentence": "Set deadzone for sticks on gamepad: _PARAM1_ to _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;\r", + "const newDeadzone = eventsFunctionContext.getArgument(\"deadzone\");\r", + "\r", + "// https://github.com/4ian/GDevelop-extensions/pull/33#issuecomment-618224857\r", + "gdjs._extensionController.getPlayer(playerId).deadzone = gdjs.evtTools.common.clamp(newDeadzone, 0, 1);\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + }, + { + "description": "Deadzone for sticks, 0.2 by default (0 to 1)", + "name": "deadzone", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Check if a stick of a gamepad is pushed in a given direction.", + "fullName": "Gamepad stick pushed (axis)", + "functionType": "Condition", + "name": "C_Axis_pushed", + "sentence": "_PARAM2_ stick of gamepad _PARAM1_ is pushed in direction _PARAM3_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;\r", + "const stick = eventsFunctionContext.getArgument(\"stick\").toUpperCase();\r", + "const direction = eventsFunctionContext.getArgument(\"direction\").toUpperCase();\r", + "\r", + "if (stick != \"LEFT\" && stick != \"RIGHT\") {\r", + " console.error('Parameter stick in condition: \"Gamepad stick pushed (axis)\", is not valid, must be LEFT or RIGHT');\r", + " return;\r", + "}\r", + "if (direction != \"UP\" && direction != \"DOWN\" && direction != \"LEFT\" && direction != \"RIGHT\" && direction != \"ANY\") {\r", + " console.error('Parameter direction in condition: \"Gamepad stick pushed (axis)\", is not valid, must be UP, DOWN, LEFT or RIGHT');\r", + " return;\r", + "}\r", + "/** @type {Gamepad} */\r", + "const gamepad = gdjs._extensionController.getGamepad(playerId);\r", + "if (!gamepad) {\r", + " // The gamepad is not connected.\r", + " return;\r", + "}\r", + "const axisValueX = stick === 'RIGHT' ? gamepad.axes[2] : gamepad.axes[0];\r", + "const axisValueY = stick === 'RIGHT' ? gamepad.axes[3] : gamepad.axes[1];\r", + "eventsFunctionContext.returnValue = gdjs._extensionController.isAxisPushed(playerId, direction, axisValueX, axisValueY);\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + }, + { + "description": "Stick: \"Left\" or \"Right\"", + "name": "stick", + "supplementaryInformation": "[\"Left\",\"Right\"]", + "type": "stringWithSelector" + }, + { + "description": "Direction", + "name": "direction", + "supplementaryInformation": "[\"Up\",\"Down\",\"Left\",\"Right\",\"Any\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Return the number of connected gamepads.", + "fullName": "Connected gamepads count", + "functionType": "Expression", + "name": "ConnectedGamepadsCount", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const gamepads = navigator.getGamepads ? navigator.getGamepads() : [];\r", + "let connectedGamepadCount = 0;\r", + "for (let playerId = 0; playerId < gamepads.length; playerId++) {\r", + " // Gamepads can be disconnected and become null\r", + " if (gamepads[playerId]) {\r", + " connectedGamepadCount++;\r", + " }\r", + "}\r", + "eventsFunctionContext.returnValue = connectedGamepadCount;\r", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [], + "objectGroups": [] + }, + { + "description": "Return a string containing informations about the specified gamepad.", + "fullName": "Gamepad type", + "functionType": "StringExpression", + "name": "GamepadType", + "sentence": "Player _PARAM1_ use _PARAM2_ controller", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;", + "/** @type {Gamepad} */", + "const gamepad = gdjs._extensionController.getGamepad(playerId);", + "if (!gamepad) {", + " // The gamepad is not connected.", + " return;", + "}", + "eventsFunctionContext.returnValue = (gamepad && gamepad.id) ? gamepad.id : \"No information for player \" + (playerId + 1)", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "string" + }, + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the specified gamepad has the specified information in its description. Useful to know if the gamepad is a Xbox or PS4 controller.", + "fullName": "Gamepad type", + "functionType": "Condition", + "name": "C_Controller_type", + "sentence": "Gamepad _PARAM1_ is a _PARAM2_ controller", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;", + "const controllerType = eventsFunctionContext.getArgument(\"controller_type\").toUpperCase();", + "/** @type {Gamepad} */", + "const gamepad = gdjs._extensionController.getGamepad(playerId);", + "if (!gamepad) {", + " // The gamepad is not connected.", + " return;", + "}", + "if (controllerType == \"XBOX\") {", + " eventsFunctionContext.returnValue = gdjs._extensionController.isXbox(gamepad);", + "} else {", + " eventsFunctionContext.returnValue = gamepad ? gamepad.id.toUpperCase().indexOf(controllerType) !== -1 : false;", + "}" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + }, + { + "description": "Type: \"Xbox\", \"PS4\", \"Steam\" or \"PS3\" (among other)", + "name": "controller_type", + "type": "string" + } + ], + "objectGroups": [] + }, + { + "description": "Check if a gamepad is connected.", + "fullName": "Gamepad connected", + "functionType": "Condition", + "name": "C_Controller_X_is_connected", + "sentence": "Gamepad _PARAM1_ is plugged and connected", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;", + "/** @type {Gamepad[]} */", + "const gamepads = navigator.getGamepads ? navigator.getGamepads() : [];", + "// If gamepad was disconnected it will be null (so this will return false)", + "// If gamepad was never connected it will be undefined (so this will return false)", + "eventsFunctionContext.returnValue = !!gamepads[playerId];" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Generate a vibration on the specified controller. Might only work if the game is running in a recent web browser.", + "fullName": "Gamepad vibration", + "functionType": "Action", + "name": "A_Vibrate_controller", + "sentence": "Make gamepad _PARAM1_ vibrate for _PARAM2_ seconds", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;", + "const duration = eventsFunctionContext.getArgument(\"Duration\") || 1;", + "/** @type {Gamepad} */", + "const gamepad = gdjs._extensionController.getGamepad(playerId);", + "if (!gamepad) {", + " // The gamepad is not connected.", + " return;", + "}", + "//Vibration work only on game in browser.", + "if (gamepad.vibrationActuator) {", + " gamepad.vibrationActuator.playEffect(\"dual-rumble\", {", + " startDelay: 0,", + " duration: duration * 1000,", + " weakMagnitude: 1.0,", + " strongMagnitude: 1.0", + " });", + "}" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + }, + { + "description": "Time of the vibration, in seconds (optional, default value is 1)", + "name": "Duration", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Generate an advanced vibration on the specified controller. Incompatible with Firefox.", + "fullName": "Advanced gamepad vibration", + "functionType": "Action", + "name": "A_Advanced_Vibration_Controller", + "sentence": "Make gamepad _PARAM1_ vibrate for _PARAM2_ seconds with the vibration magnitude of _PARAM3_ and _PARAM4_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const { clamp } = gdjs.evtTools.common;", + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;", + "const duration = eventsFunctionContext.getArgument(\"Duration\") || 1;", + "const strongRumbleMagnitude = clamp(eventsFunctionContext.getArgument(\"StrongMagnitude\"), 0, 1);", + "const weakRumbleMagnitude = clamp(eventsFunctionContext.getArgument(\"WeakMagnitude\"), 0, 1);", + "/** @type {Gamepad} */", + "const gamepad = gdjs._extensionController.getGamepad(playerId);", + "if (!gamepad) {", + " // The gamepad is not connected.", + " return;", + "}", + "//Vibration work only on game in browser.", + "if (gamepad.vibrationActuator) {", + " gamepad.vibrationActuator.playEffect(\"dual-rumble\", {", + " startDelay: 0,", + " duration: duration * 1000,", + " weakMagnitude: weakRumbleMagnitude,", + " strongMagnitude: strongRumbleMagnitude", + " });", + "}", + "const player = gdjs._extensionController.getPlayer(playerId)", + "player.rumble.duration = duration;", + "player.rumble.elapsedTime = 0;", + "player.rumble.weakMagnitude = weakRumbleMagnitude;", + "player.rumble.strongMagnitude = strongRumbleMagnitude;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + }, + { + "description": "Time of the vibration, in seconds (optional, default value is 1)", + "name": "Duration", + "type": "expression" + }, + { + "description": "Strong rumble magnitude (from 0 to 1)", + "name": "StrongMagnitude", + "type": "expression" + }, + { + "description": "Weak rumble magnitude (from 0 to 1)", + "name": "WeakMagnitude", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change a vibration on the specified controller. Incompatible with Firefox.", + "fullName": "Change gamepad active vibration", + "functionType": "Action", + "name": "A_Change_Vibration_Magnitude", + "sentence": "Change the vibration magnitude of _PARAM2_ & _PARAM3_ on gamepad _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const { clamp } = gdjs.evtTools.common;", + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;", + "const player = gdjs._extensionController.getPlayer(playerId);", + "const elapsedTime = player.rumble.elapsedTime || 0;", + "const originalDuration = player.rumble.duration || 1;", + "const strongRumbleMagnitude = clamp(eventsFunctionContext.getArgument(\"StrongMagnitude\"), 0, 1);", + "const weakRumbleMagnitude = clamp(eventsFunctionContext.getArgument(\"WeakMagnitude\"), 0, 1);", + "/** @type {Gamepad} */", + "const gamepad = gdjs._extensionController.getGamepad(playerId);", + "if (!gamepad) {", + " // The gamepad is not connected.", + " return;", + "}", + "if (originalDuration - elapsedTime <= 0) return;", + "//Vibration work only on game in browser.", + "if (gamepad.vibrationActuator) {", + " gamepad.vibrationActuator.playEffect(\"dual-rumble\", {", + " startDelay: 0,", + " duration: 1000 * (originalDuration - elapsedTime),", + " weakMagnitude: weakRumbleMagnitude,", + " strongMagnitude: strongRumbleMagnitude", + " });", + "}", + "", + "player.rumble.weakMagnitude = weakRumbleMagnitude;", + "player.rumble.strongMagnitude = strongRumbleMagnitude;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + }, + { + "description": "Strong rumble magnitude (from 0 to 1)", + "name": "StrongMagnitude", + "type": "expression" + }, + { + "description": "Weak rumble magnitude (from 0 to 1)", + "name": "WeakMagnitude", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Check if any button is released on a gamepad.", + "fullName": "Any gamepad button released", + "functionType": "Condition", + "name": "C_any_button_released", + "sentence": "Any button of gamepad _PARAM1_ is released", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "\r", + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;\r", + "const player = gdjs._extensionController.getPlayer(playerId)\r", + "eventsFunctionContext.returnValue = player.isAnyButtonReleased();" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Return the strength of the weak vibration motor on the gamepad of a player.", + "fullName": "Weak rumble magnitude", + "functionType": "Expression", + "name": "WeakVibrationMagnitude", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;\r", + "eventsFunctionContext.returnValue = gdjs._extensionController.getPlayer(playerId).rumble.weakMagnitude;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Return the strength of the strong vibration motor on the gamepad of a player.", + "fullName": "Strong rumble magnitude", + "functionType": "Expression", + "name": "StrongVibrationMagnitude", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const playerId = eventsFunctionContext.getArgument(\"PlayerId\") - 1;\r", + "eventsFunctionContext.returnValue = gdjs._extensionController.getPlayer(playerId).rumble.strongMagnitude;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "The gamepad identifier: 1, 2, 3 or 4", + "name": "PlayerId", + "type": "expression" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onFirstSceneLoaded" + }, + { + "functionName": "onSceneLoaded" + }, + { + "functionName": "onScenePostEvents" + }, + { + "functionName": "AcceleratedSpeed" + }, + { + "functionName": "TriggerPressure" + }, + { + "functionName": "StickForce" + }, + { + "functionName": "StickRotationValue" + }, + { + "functionName": "StickAngle" + }, + { + "functionName": "AxisValue" + }, + { + "functionName": "StickForceX" + }, + { + "functionName": "StickForceY" + }, + { + "functionName": "C_Button_released" + }, + { + "functionName": "IsButtonJustPressed" + }, + { + "functionName": "LastButtonID" + }, + { + "functionName": "C_Any_Button_pressed" + }, + { + "functionName": "LastButtonString" + }, + { + "functionName": "GamepadCount" + }, + { + "functionName": "C_Button_pressed" + }, + { + "functionName": "Deadzone" + }, + { + "functionName": "A_Set_deadzone" + }, + { + "functionName": "C_Axis_pushed" + }, + { + "functionName": "ConnectedGamepadsCount" + }, + { + "functionName": "GamepadType" + }, + { + "functionName": "C_Controller_type" + }, + { + "functionName": "C_Controller_X_is_connected" + }, + { + "functionName": "A_Vibrate_controller" + }, + { + "functionName": "A_Advanced_Vibration_Controller" + }, + { + "functionName": "A_Change_Vibration_Magnitude" + }, + { + "functionName": "C_any_button_released" + }, + { + "functionName": "WeakVibrationMagnitude" + }, + { + "functionName": "StrongVibrationMagnitude" + } + ] + }, + "eventsBasedBehaviors": [ + { + "description": "Control a platformer character with a gamepad.", + "fullName": "Platformer gamepad mapper", + "helpPath": "", + "iconUrl": "", + "name": "PlatformerGamepadMapper", + "objectType": "", + "previewIconUrl": "", + "quickCustomizationVisibility": "hidden", + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "doStepPreEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Controller_X_is_connected" + }, + "parameters": [ + "", + "GamepadIdentifier", + "" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "UseArrows", + "True", + "" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Button_pressed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Left\"", + "\"Left\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlatformBehavior::SimulateLeftKey" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Button_pressed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Right\"", + "\"Left\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlatformBehavior::SimulateRightKey" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Button_pressed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Up\"", + "\"Left\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlatformBehavior::SimulateUpKey" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + }, + { + "type": { + "value": "PlatformBehavior::SimulateLadderKey" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Button_pressed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Down\"", + "\"Left\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlatformBehavior::SimulateDownKey" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "UseLeftStick", + "True", + "" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Left\"", + "\"Left\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlatformBehavior::SimulateLeftKey" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Left\"", + "\"Right\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlatformBehavior::SimulateRightKey" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Left\"", + "\"Up\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlatformBehavior::SimulateUpKey" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + }, + { + "type": { + "value": "PlatformBehavior::SimulateLadderKey" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Left\"", + "\"Down\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlatformBehavior::SimulateDownKey" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "UseRightStick", + "True", + "" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Right\"", + "\"Left\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlatformBehavior::SimulateLeftKey" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Right\"", + "\"Right\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlatformBehavior::SimulateRightKey" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Right\"", + "\"Up\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlatformBehavior::SimulateUpKey" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + }, + { + "type": { + "value": "PlatformBehavior::SimulateLadderKey" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Right\"", + "\"Down\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlatformBehavior::SimulateDownKey" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Button_pressed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "Buttons[JumpButton]", + "\"Left\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "PlatformBehavior::SimulateJumpKey" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + } + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::PlatformerGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "doStepPreEvents" + } + ] + }, + "propertyDescriptors": [ + { + "value": "", + "type": "Behavior", + "label": "Platformer character behavior", + "extraInformation": [ + "PlatformBehavior::PlatformerObjectBehavior" + ], + "choices": [], + "name": "PlatformerCharacter" + }, + { + "value": "1", + "type": "Number", + "label": "Gamepad identifier (1, 2, 3 or 4)", + "name": "GamepadIdentifier" + }, + { + "value": "true", + "type": "Boolean", + "label": "Use directional pad", + "group": "Controls", + "name": "UseArrows" + }, + { + "value": "true", + "type": "Boolean", + "label": "Use left stick", + "group": "Controls", + "name": "UseLeftStick" + }, + { + "value": "", + "type": "Boolean", + "label": "Use right stick", + "group": "Controls", + "name": "UseRightStick" + }, + { + "value": "A or Cross", + "type": "Choice", + "label": "Jump button", + "group": "Controls", + "choices": [ + { + "label": "A or Cross", + "value": "A or Cross" + }, + { + "label": "B or Circle", + "value": "B or Circle" + }, + { + "label": "X or Square", + "value": "X or Square" + }, + { + "label": "Y or Triangle", + "value": "Y or Triangle" + }, + { + "label": "LB or L1", + "value": "LB or L1" + }, + { + "label": "RB or R1", + "value": "RB or R1" + }, + { + "label": "LT or L2", + "value": "LT or L2" + }, + { + "label": "RT or R2", + "value": "RT or R2" + } + ], + "name": "JumpButton" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "PlatformerCharacter" + }, + { + "propertyName": "GamepadIdentifier" + }, + { + "folderName": "Controls", + "children": [ + { + "propertyName": "UseArrows" + }, + { + "propertyName": "UseLeftStick" + }, + { + "propertyName": "UseRightStick" + }, + { + "propertyName": "JumpButton" + } + ] + } + ] + } + }, + { + "description": "Control a 3D physics character with a gamepad.", + "fullName": "3D platformer gamepad mapper", + "helpPath": "", + "iconUrl": "", + "name": "Platformer3DGamepadMapper", + "objectType": "", + "previewIconUrl": "", + "quickCustomizationVisibility": "hidden", + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "doStepPreEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Controller_X_is_connected" + }, + "parameters": [ + "", + "GamepadIdentifier", + "" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::StickForce" + }, + "parameters": [ + "", + ">", + "0", + "GamepadIdentifier", + "JoystickIdentifier", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "Physics3D::PhysicsCharacter3D::SetForwardAngle" + }, + "parameters": [ + "Object", + "PhysicsCharacter3D", + "=", + "Gamepads::StickAngle(GamepadIdentifier, JoystickIdentifier) + CameraAngle(Object.Layer())" + ] + }, + { + "type": { + "value": "Physics3D::PhysicsCharacter3D::SimulateStick" + }, + "parameters": [ + "Object", + "PhysicsCharacter3D", + "-90", + "Gamepads::StickForce(GamepadIdentifier, JoystickIdentifier)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Button_pressed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "Buttons[JumpButton]", + "\"Left\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "Physics3D::PhysicsCharacter3D::SimulateJumpKey" + }, + "parameters": [ + "Object", + "PhysicsCharacter3D" + ] + } + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::Platformer3DGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "doStepPreEvents" + } + ] + }, + "propertyDescriptors": [ + { + "value": "", + "type": "Behavior", + "label": "3D physics character", + "extraInformation": [ + "Physics3D::PhysicsCharacter3D" + ], + "choices": [], + "name": "PhysicsCharacter3D" + }, + { + "value": "1", + "type": "Number", + "label": "Gamepad identifier (1, 2, 3 or 4)", + "name": "GamepadIdentifier" + }, + { + "value": "Left", + "type": "Choice", + "label": "Walk joystick", + "group": "Controls", + "choices": [ + { + "label": "Left", + "value": "Left" + }, + { + "label": "Right", + "value": "Right" + } + ], + "name": "JoystickIdentifier" + }, + { + "value": "A or Cross", + "type": "Choice", + "label": "Jump button", + "group": "Controls", + "choices": [ + { + "label": "A or Cross", + "value": "A or Cross" + }, + { + "label": "B or Circle", + "value": "B or Circle" + }, + { + "label": "X or Square", + "value": "X or Square" + }, + { + "label": "Y or Triangle", + "value": "Y or Triangle" + }, + { + "label": "LB or L1", + "value": "LB or L1" + }, + { + "label": "RB or R1", + "value": "RB or R1" + }, + { + "label": "LT or L2", + "value": "LT or L2" + }, + { + "label": "RT or R2", + "value": "RT or R2" + } + ], + "name": "JumpButton" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "PhysicsCharacter3D" + }, + { + "propertyName": "GamepadIdentifier" + }, + { + "folderName": "Controls", + "children": [ + { + "propertyName": "JoystickIdentifier" + }, + { + "propertyName": "JumpButton" + } + ] + } + ] + } + }, + { + "description": "Control a 3D physics character with a gamepad.", + "fullName": "3D shooter gamepad mapper", + "helpPath": "", + "iconUrl": "", + "name": "Shooter3DGamepadMapper", + "objectType": "", + "previewIconUrl": "", + "quickCustomizationVisibility": "hidden", + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "doStepPreEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Controller_X_is_connected" + }, + "parameters": [ + "", + "GamepadIdentifier", + "" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::StickForce" + }, + "parameters": [ + "", + ">", + "0", + "GamepadIdentifier", + "WalkStick", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "Physics3D::PhysicsCharacter3D::SimulateStick" + }, + "parameters": [ + "Object", + "PhysicsCharacter3D", + "Gamepads::StickAngle(GamepadIdentifier, WalkStick)", + "Gamepads::StickForce(GamepadIdentifier, WalkStick)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Button_pressed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "Buttons[JumpButton]", + "\"Left\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "Physics3D::PhysicsCharacter3D::SimulateJumpKey" + }, + "parameters": [ + "Object", + "PhysicsCharacter3D" + ] + } + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::Shooter3DGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "doStepPreEvents" + } + ] + }, + "propertyDescriptors": [ + { + "value": "", + "type": "Behavior", + "label": "3D physics character", + "extraInformation": [ + "Physics3D::PhysicsCharacter3D" + ], + "choices": [], + "name": "PhysicsCharacter3D" + }, + { + "value": "1", + "type": "Number", + "label": "Gamepad identifier (1, 2, 3 or 4)", + "name": "GamepadIdentifier" + }, + { + "value": "Left", + "type": "Choice", + "label": "Walk joystick", + "group": "Controls", + "choices": [ + { + "label": "Left", + "value": "Left" + }, + { + "label": "Right", + "value": "Right" + } + ], + "name": "WalkStick" + }, + { + "value": "Right", + "type": "Choice", + "label": "Camera joystick", + "group": "Controls", + "choices": [ + { + "label": "Left", + "value": "Left" + }, + { + "label": "Right", + "value": "Right" + } + ], + "name": "CameraStick" + }, + { + "value": "A or Cross", + "type": "Choice", + "label": "Jump button", + "group": "Controls", + "choices": [ + { + "label": "A or Cross", + "value": "A or Cross" + }, + { + "label": "B or Circle", + "value": "B or Circle" + }, + { + "label": "X or Square", + "value": "X or Square" + }, + { + "label": "Y or Triangle", + "value": "Y or Triangle" + }, + { + "label": "LB or L1", + "value": "LB or L1" + }, + { + "label": "RB or R1", + "value": "RB or R1" + }, + { + "label": "LT or L2", + "value": "LT or L2" + }, + { + "label": "RT or R2", + "value": "RT or R2" + } + ], + "name": "JumpButton" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "PhysicsCharacter3D" + }, + { + "propertyName": "GamepadIdentifier" + }, + { + "folderName": "Controls", + "children": [ + { + "propertyName": "WalkStick" + }, + { + "propertyName": "CameraStick" + }, + { + "propertyName": "JumpButton" + } + ] + } + ] + } + }, + { + "description": "Control camera rotations with a gamepad.", + "fullName": "First person camera gamepad mapper", + "helpPath": "", + "iconUrl": "", + "name": "FirstPersonGamepadMapper", + "objectType": "", + "previewIconUrl": "", + "quickCustomizationVisibility": "hidden", + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "doStepPreEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "TODO It's probably a bad idea to rotate the object around Y." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CurrentRotationSpeedZ", + "=", + "Gamepads::AcceleratedSpeed(CurrentRotationSpeedZ, Gamepads::StickForceX(GamepadIdentifier, CameraStick) * HorizontalRotationSpeedMax, HorizontalRotationSpeedMax, HorizontalRotationAcceleration, HorizontalRotationDeceleration)" + ] + }, + { + "type": { + "value": "SetAngle" + }, + "parameters": [ + "Object", + "+", + "CurrentRotationSpeedZ * TimeDelta()" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CurrentRotationSpeedY", + "=", + "Gamepads::AcceleratedSpeed(CurrentRotationSpeedY, Gamepads::StickForceY(GamepadIdentifier, CameraStick) * VerticalRotationSpeedMax, VerticalRotationSpeedMax, VerticalRotationAcceleration, VerticalRotationDeceleration)" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetRotationY" + }, + "parameters": [ + "Object", + "Object3D", + "+", + "CurrentRotationSpeedY * TimeDelta()" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetRotationY" + }, + "parameters": [ + "Object", + "Object3D", + "=", + "clamp(Object.Object3D::RotationY(), VerticalAngleMin, VerticalAngleMax)" + ] + }, + { + "type": { + "value": "Gamepads::FirstPersonGamepadMapper::LookFromObjectEyes" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Move the camera to look though _PARAM1_ eyes. The object must look to the right when all its angles are 0 and the top of its head be toward Z+.", + "fullName": "Look through object eyes", + "functionType": "Action", + "group": "Layers and cameras", + "name": "LookFromObjectEyes", + "private": true, + "sentence": "Move the camera to look though _PARAM0_ eyes", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "CentreCamera" + }, + "parameters": [ + "", + "Object", + "", + "Object.Layer()", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraZ" + }, + "parameters": [ + "", + "=", + "Object.Object3D::Z() + Object.Object3D::Depth() + OffsetZ", + "", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraRotationX" + }, + "parameters": [ + "", + "=", + "- Object.Object3D::RotationY() + 90", + "GetArgumentAsString(\"Layer\")", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraRotationY" + }, + "parameters": [ + "", + "=", + "Object.Object3D::RotationX()", + "GetArgumentAsString(\"Layer\")", + "" + ] + }, + { + "type": { + "value": "SetCameraAngle" + }, + "parameters": [ + "", + "=", + "Object.Angle() + 90", + "Object.Layer()", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the maximum horizontal rotation speed of the object.", + "fullName": "Maximum horizontal rotation speed", + "functionType": "ExpressionAndCondition", + "group": "First person camera gamepad mapper horizontal rotation configuration", + "name": "HorizontalRotationSpeedMax", + "sentence": "the maximum horizontal rotation speed", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "HorizontalRotationSpeedMax" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "HorizontalRotationSpeedMax", + "group": "First person camera gamepad mapper horizontal rotation configuration", + "name": "SetHorizontalRotationSpeedMax", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "HorizontalRotationSpeedMax", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the horizontal rotation acceleration of the object.", + "fullName": "Horizontal rotation acceleration", + "functionType": "ExpressionAndCondition", + "group": "First person camera gamepad mapper horizontal rotation configuration", + "name": "HorizontalRotationAcceleration", + "sentence": "the horizontal rotation acceleration", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "HorizontalRotationAcceleration" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "HorizontalRotationAcceleration", + "group": "First person camera gamepad mapper horizontal rotation configuration", + "name": "SetHorizontalRotationAcceleration", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "HorizontalRotationAcceleration", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the horizontal rotation deceleration of the object.", + "fullName": "Horizontal rotation deceleration", + "functionType": "ExpressionAndCondition", + "group": "First person camera gamepad mapper horizontal rotation configuration", + "name": "HorizontalRotationDeceleration", + "sentence": "the horizontal rotation deceleration", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "HorizontalRotationDeceleration" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "HorizontalRotationDeceleration", + "group": "First person camera gamepad mapper horizontal rotation configuration", + "name": "SetHorizontalRotationDeceleration", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "HorizontalRotationDeceleration", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the maximum vertical rotation speed of the object.", + "fullName": "Maximum vertical rotation speed", + "functionType": "ExpressionAndCondition", + "group": "First person camera gamepad mapper vertical rotation configuration", + "name": "VerticalRotationSpeedMax", + "sentence": "the maximum vertical rotation speed", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "VerticalRotationSpeedMax" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "VerticalRotationSpeedMax", + "group": "First person camera gamepad mapper vertical rotation configuration", + "name": "SetVerticalRotationSpeedMax", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "VerticalRotationSpeedMax", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the vertical rotation acceleration of the object.", + "fullName": "Vertical rotation acceleration", + "functionType": "ExpressionAndCondition", + "group": "First person camera gamepad mapper vertical rotation configuration", + "name": "VerticalRotationAcceleration", + "sentence": "the vertical rotation acceleration", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "VerticalRotationAcceleration" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "VerticalRotationAcceleration", + "group": "First person camera gamepad mapper vertical rotation configuration", + "name": "SetVerticalRotationAcceleration", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "VerticalRotationAcceleration", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the vertical rotation deceleration of the object.", + "fullName": "Vertical rotation deceleration", + "functionType": "ExpressionAndCondition", + "group": "First person camera gamepad mapper vertical rotation configuration", + "name": "VerticalRotationDeceleration", + "sentence": "the vertical rotation deceleration", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "VerticalRotationDeceleration" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "VerticalRotationDeceleration", + "group": "First person camera gamepad mapper vertical rotation configuration", + "name": "SetVerticalRotationDeceleration", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "VerticalRotationDeceleration", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the minimum vertical camera angle of the object.", + "fullName": "Minimum vertical camera angle", + "functionType": "ExpressionAndCondition", + "group": "First person camera gamepad mapper vertical rotation configuration", + "name": "VerticalAngleMin", + "sentence": "the minimum vertical camera angle", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "VerticalAngleMin" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "VerticalAngleMin", + "group": "First person camera gamepad mapper vertical rotation configuration", + "name": "SetVerticalAngleMin", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "VerticalAngleMin", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the maximum vertical camera angle of the object.", + "fullName": "Maximum vertical camera angle", + "functionType": "ExpressionAndCondition", + "group": "First person camera gamepad mapper vertical rotation configuration", + "name": "VerticalAngleMax", + "sentence": "the maximum vertical camera angle", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "VerticalAngleMax" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "VerticalAngleMax", + "group": "First person camera gamepad mapper vertical rotation configuration", + "name": "SetVerticalAngleMax", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "VerticalAngleMax", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the z position offset of the object.", + "fullName": "Z position offset", + "functionType": "ExpressionAndCondition", + "group": "First person camera gamepad mapper position configuration", + "name": "OffsetZ", + "sentence": "the z position offset", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "OffsetZ" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "OffsetZ", + "group": "First person camera gamepad mapper position configuration", + "name": "SetOffsetZ", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "OffsetZ", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::FirstPersonGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "doStepPreEvents" + }, + { + "folderName": "Layers and cameras", + "children": [ + { + "functionName": "LookFromObjectEyes" + } + ] + }, + { + "folderName": "First person camera gamepad mapper horizontal rotation configuration", + "children": [ + { + "functionName": "HorizontalRotationSpeedMax" + }, + { + "functionName": "SetHorizontalRotationSpeedMax" + }, + { + "functionName": "HorizontalRotationAcceleration" + }, + { + "functionName": "SetHorizontalRotationAcceleration" + }, + { + "functionName": "HorizontalRotationDeceleration" + }, + { + "functionName": "SetHorizontalRotationDeceleration" + } + ] + }, + { + "folderName": "First person camera gamepad mapper vertical rotation configuration", + "children": [ + { + "functionName": "VerticalRotationSpeedMax" + }, + { + "functionName": "SetVerticalRotationSpeedMax" + }, + { + "functionName": "VerticalRotationAcceleration" + }, + { + "functionName": "SetVerticalRotationAcceleration" + }, + { + "functionName": "VerticalRotationDeceleration" + }, + { + "functionName": "SetVerticalRotationDeceleration" + }, + { + "functionName": "VerticalAngleMin" + }, + { + "functionName": "SetVerticalAngleMin" + }, + { + "functionName": "VerticalAngleMax" + }, + { + "functionName": "SetVerticalAngleMax" + } + ] + }, + { + "folderName": "First person camera gamepad mapper position configuration", + "children": [ + { + "functionName": "OffsetZ" + }, + { + "functionName": "SetOffsetZ" + } + ] + } + ] + }, + "propertyDescriptors": [ + { + "value": "", + "type": "Behavior", + "label": "3D capability", + "extraInformation": [ + "Scene3D::Base3DBehavior" + ], + "choices": [], + "name": "Object3D" + }, + { + "value": "1", + "type": "Number", + "label": "Gamepad identifier (1, 2, 3 or 4)", + "name": "GamepadIdentifier" + }, + { + "value": "Right", + "type": "Choice", + "label": "Camera joystick", + "choices": [ + { + "label": "Left", + "value": "Left" + }, + { + "label": "Right", + "value": "Right" + } + ], + "name": "CameraStick" + }, + { + "value": "180", + "type": "Number", + "unit": "AngularSpeed", + "label": "Maximum rotation speed", + "group": "Horizontal rotation", + "name": "HorizontalRotationSpeedMax" + }, + { + "value": "360", + "type": "Number", + "label": "Rotation acceleration", + "group": "Horizontal rotation", + "name": "HorizontalRotationAcceleration" + }, + { + "value": "720", + "type": "Number", + "label": "Rotation deceleration", + "group": "Horizontal rotation", + "name": "HorizontalRotationDeceleration" + }, + { + "value": "120", + "type": "Number", + "unit": "AngularSpeed", + "label": "Maximum rotation speed", + "group": "Vertical rotation", + "name": "VerticalRotationSpeedMax" + }, + { + "value": "240", + "type": "Number", + "label": "Rotation acceleration", + "group": "Vertical rotation", + "name": "VerticalRotationAcceleration" + }, + { + "value": "480", + "type": "Number", + "label": "Rotation deceleration", + "group": "Vertical rotation", + "name": "VerticalRotationDeceleration" + }, + { + "value": "-90", + "type": "Number", + "unit": "DegreeAngle", + "label": "Minimum angle", + "group": "Vertical rotation", + "name": "VerticalAngleMin" + }, + { + "value": "90", + "type": "Number", + "unit": "DegreeAngle", + "label": "Maximum angle", + "group": "Vertical rotation", + "name": "VerticalAngleMax" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Z position offset", + "group": "Position", + "name": "OffsetZ" + }, + { + "value": "0", + "type": "Number", + "unit": "AngularSpeed", + "label": "Current rotation speed Z", + "hidden": true, + "name": "CurrentRotationSpeedZ" + }, + { + "value": "0", + "type": "Number", + "unit": "AngularSpeed", + "label": "Current rotation speed Y", + "hidden": true, + "name": "CurrentRotationSpeedY" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "Object3D" + }, + { + "propertyName": "GamepadIdentifier" + }, + { + "propertyName": "CameraStick" + }, + { + "folderName": "Horizontal rotation", + "children": [ + { + "propertyName": "HorizontalRotationSpeedMax" + }, + { + "propertyName": "HorizontalRotationAcceleration" + }, + { + "propertyName": "HorizontalRotationDeceleration" + } + ] + }, + { + "folderName": "Vertical rotation", + "children": [ + { + "propertyName": "VerticalRotationSpeedMax" + }, + { + "propertyName": "VerticalRotationAcceleration" + }, + { + "propertyName": "VerticalRotationDeceleration" + }, + { + "propertyName": "VerticalAngleMin" + }, + { + "propertyName": "VerticalAngleMax" + } + ] + }, + { + "folderName": "Position", + "children": [ + { + "propertyName": "OffsetZ" + } + ] + }, + { + "propertyName": "CurrentRotationSpeedZ" + }, + { + "propertyName": "CurrentRotationSpeedY" + } + ] + } + }, + { + "description": "Control a 3D physics car with a gamepad.", + "fullName": "3D car gamepad mapper", + "helpPath": "", + "iconUrl": "", + "name": "PhysicsCar3DGamepadMapper", + "objectType": "", + "previewIconUrl": "", + "quickCustomizationVisibility": "hidden", + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "doStepPreEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Controller_X_is_connected" + }, + "parameters": [ + "", + "GamepadIdentifier", + "" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "UseArrows", + "True", + "" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Button_pressed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Left\"", + "\"Left\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "Physics3D::PhysicsCar3D::SimulateLeftKey" + }, + "parameters": [ + "Object", + "PhysicsCar3D" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Button_pressed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Right\"", + "\"Left\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "Physics3D::PhysicsCar3D::SimulateRightKey" + }, + "parameters": [ + "Object", + "PhysicsCar3D" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "UseLeftStick", + "True", + "" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "1", + "\"Left\"", + "\"Any\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "Physics3D::PhysicsCar3D::SimulateSteeringStick" + }, + "parameters": [ + "Object", + "PhysicsCar3D", + "Gamepads::StickForceX(GamepadIdentifier, \"Left\")" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "UseRightStick", + "True", + "" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "1", + "\"Right\"", + "\"Any\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "Physics3D::PhysicsCar3D::SimulateSteeringStick" + }, + "parameters": [ + "Object", + "PhysicsCar3D", + "Gamepads::StickForceX(GamepadIdentifier, \"Right\")" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "Gamepads::C_Button_pressed" + }, + "parameters": [ + "", + "1", + "\"LT\"", + "\"Up\"" + ] + }, + { + "type": { + "value": "Gamepads::C_Button_pressed" + }, + "parameters": [ + "", + "1", + "\"RT\"", + "\"Up\"" + ] + } + ] + } + ], + "actions": [ + { + "type": { + "value": "Physics3D::PhysicsCar3D::SimulateAcceleratorStick" + }, + "parameters": [ + "Object", + "PhysicsCar3D", + "Gamepads::TriggerPressure(GamepadIdentifier, \"RT\") - Gamepads::TriggerPressure(GamepadIdentifier, \"LT\")" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Button_pressed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "Buttons[HandBrakeButton]", + "\"Left\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "Physics3D::PhysicsCar3D::SimulateHandBrakeKey" + }, + "parameters": [ + "Object", + "PhysicsCar3D" + ] + } + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::PhysicsCar3DGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "doStepPreEvents" + } + ] + }, + "propertyDescriptors": [ + { + "value": "", + "type": "Behavior", + "label": "3D physics car", + "extraInformation": [ + "Physics3D::PhysicsCar3D" + ], + "choices": [], + "name": "PhysicsCar3D" + }, + { + "value": "1", + "type": "Number", + "label": "Gamepad identifier (1, 2, 3 or 4)", + "name": "GamepadIdentifier" + }, + { + "value": "true", + "type": "Boolean", + "label": "Use directional pad", + "group": "Controls", + "name": "UseArrows" + }, + { + "value": "true", + "type": "Boolean", + "label": "Use left stick", + "group": "Controls", + "name": "UseLeftStick" + }, + { + "value": "", + "type": "Boolean", + "label": "Use right stick", + "group": "Controls", + "name": "UseRightStick" + }, + { + "value": "B or Circle", + "type": "Choice", + "label": "Hand brake button", + "group": "Controls", + "choices": [ + { + "label": "A or Cross", + "value": "A or Cross" + }, + { + "label": "B or Circle", + "value": "B or Circle" + }, + { + "label": "X or Square", + "value": "X or Square" + }, + { + "label": "Y or Triangle", + "value": "Y or Triangle" + }, + { + "label": "LB or L1", + "value": "LB or L1" + }, + { + "label": "RB or R1", + "value": "RB or R1" + }, + { + "label": "LT or L2", + "value": "LT or L2" + }, + { + "label": "RT or R2", + "value": "RT or R2" + } + ], + "name": "HandBrakeButton" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "PhysicsCar3D" + }, + { + "propertyName": "GamepadIdentifier" + }, + { + "folderName": "Controls", + "children": [ + { + "propertyName": "UseArrows" + }, + { + "propertyName": "UseLeftStick" + }, + { + "propertyName": "UseRightStick" + }, + { + "propertyName": "HandBrakeButton" + } + ] + } + ] + } + }, + { + "description": "Control a top-down character with a gamepad.", + "fullName": "Top-down gamepad mapper", + "helpPath": "", + "iconUrl": "", + "name": "TopDownGamepadMapper", + "objectType": "", + "previewIconUrl": "", + "quickCustomizationVisibility": "hidden", + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "doStepPreEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Controller_X_is_connected" + }, + "parameters": [ + "", + "GamepadIdentifier", + "" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "UseArrows", + "True", + "" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Button_pressed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Left\"", + "\"Left\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "TopDownMovementBehavior::SimulateLeftKey" + }, + "parameters": [ + "Object", + "TopDownMovement" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Button_pressed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Right\"", + "\"Left\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "TopDownMovementBehavior::SimulateRightKey" + }, + "parameters": [ + "Object", + "TopDownMovement" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Button_pressed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Up\"", + "\"Left\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "TopDownMovementBehavior::SimulateUpKey" + }, + "parameters": [ + "Object", + "TopDownMovement" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Button_pressed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Down\"", + "\"Left\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "TopDownMovementBehavior::SimulateDownKey" + }, + "parameters": [ + "Object", + "TopDownMovement" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "UseLeftStick", + "True", + "" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "StickMode", + "=", + "\"Analog\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "TopDownMovementBehavior::SimulateStick" + }, + "parameters": [ + "Object", + "TopDownMovement", + "Gamepads::StickRotationValue(GamepadIdentifier, \"Left\")", + "Gamepads::StickForce(GamepadIdentifier, \"Left\")" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "StickMode", + "=", + "\"360°\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "TopDownMovementBehavior::SimulateStick" + }, + "parameters": [ + "Object", + "TopDownMovement", + "Gamepads::StickRotationValue(GamepadIdentifier, \"Left\")", + "sign(Gamepads::StickForce(GamepadIdentifier, \"Left\"))" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "StickMode", + "=", + "\"8 Directions\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Left\"", + "\"Left\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "TopDownMovementBehavior::SimulateLeftKey" + }, + "parameters": [ + "Object", + "TopDownMovement" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Left\"", + "\"Right\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "TopDownMovementBehavior::SimulateRightKey" + }, + "parameters": [ + "Object", + "TopDownMovement" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Left\"", + "\"Up\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "TopDownMovementBehavior::SimulateUpKey" + }, + "parameters": [ + "Object", + "TopDownMovement" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Left\"", + "\"Down\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "TopDownMovementBehavior::SimulateDownKey" + }, + "parameters": [ + "Object", + "TopDownMovement" + ] + } + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "UseRightStick", + "True", + "" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "StickMode", + "=", + "\"Analog\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "TopDownMovementBehavior::SimulateStick" + }, + "parameters": [ + "Object", + "TopDownMovement", + "Gamepads::StickRotationValue(GamepadIdentifier, \"Right\")", + "Gamepads::StickForce(GamepadIdentifier, \"Right\")" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "StickMode", + "=", + "\"360°\"" + ] + } + ], + "actions": [ + { + "type": { + "value": "TopDownMovementBehavior::SimulateStick" + }, + "parameters": [ + "Object", + "TopDownMovement", + "sign(Gamepads::StickForce(GamepadIdentifier, \"Right\"))", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "StringVariable" + }, + "parameters": [ + "StickMode", + "=", + "\"8 Directions\"" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Right\"", + "\"Left\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "TopDownMovementBehavior::SimulateLeftKey" + }, + "parameters": [ + "Object", + "TopDownMovement" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Right\"", + "\"Right\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "TopDownMovementBehavior::SimulateRightKey" + }, + "parameters": [ + "Object", + "TopDownMovement" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Right\"", + "\"Up\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "TopDownMovementBehavior::SimulateUpKey" + }, + "parameters": [ + "Object", + "TopDownMovement" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Gamepads::C_Axis_pushed" + }, + "parameters": [ + "", + "GamepadIdentifier", + "\"Right\"", + "\"Down\"", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "TopDownMovementBehavior::SimulateDownKey" + }, + "parameters": [ + "Object", + "TopDownMovement" + ] + } + ] + } + ] + } + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "Gamepads::TopDownGamepadMapper", + "type": "behavior" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "doStepPreEvents" + } + ] + }, + "propertyDescriptors": [ + { + "value": "", + "type": "Behavior", + "label": "Top-down movement behavior", + "extraInformation": [ + "TopDownMovementBehavior::TopDownMovementBehavior" + ], + "choices": [], + "name": "TopDownMovement" + }, + { + "value": "1", + "type": "Number", + "label": "Gamepad identifier (1, 2, 3 or 4)", + "name": "GamepadIdentifier" + }, + { + "value": "true", + "type": "Boolean", + "label": "Use directional pad", + "group": "Controls", + "name": "UseArrows" + }, + { + "value": "true", + "type": "Boolean", + "label": "Use left stick", + "group": "Controls", + "name": "UseLeftStick" + }, + { + "value": "", + "type": "Boolean", + "label": "Use right stick", + "group": "Controls", + "name": "UseRightStick" + }, + { + "value": "Analog", + "type": "Choice", + "label": "Stick mode", + "group": "Controls", + "choices": [ + { + "label": "Analog", + "value": "Analog" + }, + { + "label": "360°", + "value": "360°" + }, + { + "label": "8 Directions", + "value": "8 Directions" + } + ], + "name": "StickMode" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "TopDownMovement" + }, + { + "propertyName": "GamepadIdentifier" + }, + { + "folderName": "Controls", + "children": [ + { + "propertyName": "UseArrows" + }, + { + "propertyName": "UseLeftStick" + }, + { + "propertyName": "UseRightStick" + }, + { + "propertyName": "StickMode" + } + ] + } + ] + } + } + ], + "eventsBasedObjects": [] + }, + { + "author": "@4ian", + "category": "Game mechanic", + "dimension": "2D/3D", + "extensionNamespace": "", + "fullName": "Fire bullets", + "gdevelopVersion": ">=5.5.222", + "helpPath": "/extensions/fire-bullet/details", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0ibWRpLWJ1bGxldCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxwYXRoIGQ9Ik0xNCwyMkgxMFYyMUgxNFYyMk0xMywxMFY3SDExVjEwTDEwLDExLjVWMjBIMTRWMTEuNUwxMywxME0xMiwyQzEyLDIgMTEsMyAxMSw1VjZIMTNWNUMxMyw1IDEzLDMgMTIsMloiIC8+PC9zdmc+", + "name": "FireBullet", + "previewIconUrl": "https://resources.gdevelop-app.com/assets/Icons/bullet.svg", + "shortDescription": "Fire bullets with ammo count, reload timer, and overheat management.", + "version": "0.10.0", + "description": [ + "This extension allows objects to fire bullets. To use it, add the behavior to the object that will shoot, then use the provided action to launch another object as the bullet.", + "", + "The properties of the behavior can be used to customize:", + "- Cooldown between shots", + "- Firing multiple bullets at a time ([open the project online](https://editor.gdevelop.io/?project=example://fire-bullet))", + "- Ammo management", + "- Overheat", + "", + "The speed can be specified when using the actions to fire the bullets.", + "The bullets are automatically given a permanent force to make them move in the 2D plane (no need to use a linear movement or move them with another behavior).", + "", + "It can be used for:", + "- Twin-stick shooters ([open the project online](https://editor.gdevelop.io/?project=example://conviction-of-gun-dude-desktop))", + "- Shoot'em up ([open the project online](https://editor.gdevelop.io/?project=example://space-shooter))", + "", + "A simple example shows how to make firing patterns ([open the project online](https://editor.gdevelop.io/?project=example://firing-patterns))." + ], + "origin": { + "identifier": "FireBullet", + "name": "gdevelop-extension-store" + }, + "tags": [ + "fire", + "bullet", + "spawn", + "firerate", + "reload", + "weapon", + "ranged", + "ammo", + "overheat" + ], + "authorIds": [ + "wWP8BSlAW0UP4NeaHa2LcmmDzmH2", + "xpwUwByyImTDcHEqDUqfyg0oRBt1", + "2OwwM8ToR9dx9RJ2sAKTcrLmCB92", + "gqDaZjCfevOOxBYkK6zlhtZnXCg1" + ], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [], + "eventsFunctions": [ + { + "description": "Define helper classes JavaScript code.", + "fullName": "Define helper classes", + "functionType": "Action", + "name": "DefineHelperClasses", + "private": true, + "sentence": "Define helper classes JavaScript code", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "//@ts-ignore", + "if (gdjs.__fireBulletExtension) {", + " //@ts-ignore", + " return;", + "}", + "", + "class LocalBasis {", + " forward = new THREE.Vector3();", + " up = new THREE.Vector3();", + " right = new THREE.Vector3();", + "", + " /**", + " * @param offsetX {number}", + " */", + " getWorldOffsetX(offsetX, offsetY, offsetZ) {", + " return offsetX * this.forward.x +", + " offsetY * this.right.x +", + " offsetZ * this.up.y;", + " }", + "", + " /**", + " * @param offsetY {number}", + " */", + " getWorldOffsetY(offsetX, offsetY, offsetZ) {", + " return offsetX * this.forward.y +", + " offsetY * this.right.y +", + " offsetZ * this.up.y;", + " }", + "", + " /**", + " * @param offsetX {number}", + " */", + " getWorldOffsetZ(offsetX, offsetY, offsetZ) {", + " return offsetX * this.forward.z +", + " offsetY * this.right.z +", + " offsetZ * this.up.z;", + " }", + "}", + "", + "class CameraLocalBasis extends LocalBasis {", + " /** @type {gdjs.RuntimeObject} */", + " object;", + " rotationMatrix = new THREE.Matrix4();", + "", + " /**", + " * @param object {gdjs.RuntimeObject}", + " */", + " constructor(object) {", + " super();", + " this.object = object;", + " }", + "", + " update() {", + " const layer = this.object.getInstanceContainer().getLayer(this.object.getLayer());", + " const threeCamera = layer.getRenderer().getThreeCamera();", + " this.rotationMatrix.makeRotationFromEuler(threeCamera.rotation);", + " const elements = this.rotationMatrix.elements;", + "", + " this.forward.set(-elements[8], elements[9], -elements[10]);", + " this.right.set(elements[0], -elements[1], elements[2]);", + " this.up.crossVectors(this.forward, this.right);", + "", + " // Normalize them, just in case (they should generally be unit vectors).", + " this.forward.normalize();", + " this.right.normalize();", + " this.up.normalize();", + " }", + "}", + "", + "class ObjectLocalBasis extends LocalBasis {", + " /** @type {gdjs.RuntimeObject} */", + " object;", + " rotationMatrix = new THREE.Matrix4();", + "", + " /**", + " * @param object {gdjs.RuntimeObject}", + " */", + " constructor(object) {", + " super();", + " this.object = object;", + " }", + "", + " update() {", + " const threeObject = this.object.get3DRendererObject();", + " this.rotationMatrix.makeRotationFromEuler(threeObject.rotation);", + " const elements = this.rotationMatrix.elements;", + "", + " this.forward.set(elements[0], elements[1], elements[2]);", + " this.up.set(elements[8], elements[9], elements[10]);", + " this.right.crossVectors(this.forward, this.up);", + "", + " // Normalize them, just in case (they should generally be unit vectors).", + " this.forward.normalize();", + " this.right.normalize();", + " this.up.normalize();", + " }", + "}", + "", + "/**", + " * It can be built the follow:", + " * ", + " * `objectDefaultRotation.setFromAxisAngle(new THREE.Vector3(1, 0, 0), Math.PI/2);`", + " * ", + " * `objectDefaultRotation.multiply(new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 0, 1), -Math.PI/2));`", + " * ", + " */", + "const objectDefaultRotation = new THREE.Quaternion(0.5, 0.5, -0.5, 0.5);", + "", + "/**", + " * @param {gdjs.RuntimeObject3D} object", + " */", + "function rotateObjectToFaceSameWayAsCamera(object) {", + " const layer = object.getInstanceContainer().getLayer(object.getLayer());", + " const threeCamera = layer.getRenderer().getThreeCamera();", + " const threeObject = object.get3DRendererObject();", + "", + " threeObject.rotation.copy(threeCamera.rotation);", + " threeObject.rotation.z = -threeObject.rotation.z;", + " threeObject.rotation.x = -threeObject.rotation.x;", + " threeObject.quaternion.multiply(objectDefaultRotation);", + "", + " const {x, y, z } = threeObject.rotation;", + " object.setAngle(gdjs.toDegrees(z));", + " object.setRotationY(gdjs.toDegrees(y));", + " object.setRotationX(gdjs.toDegrees(x));", + "}", + "", + "//@ts-ignore", + "gdjs.__fireBulletExtension = {", + " CameraLocalBasis,", + " ObjectLocalBasis,", + " rotateObjectToFaceSameWayAsCamera", + "};", + "" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "fullName": "Rotate the same way as camera", + "functionType": "Action", + "name": "RotateObjectToFaceSameWayAsCamera", + "private": true, + "sentence": "Rotate _PARAM1_ to look the same way as the camera", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "", + "const { rotateObjectToFaceSameWayAsCamera } = gdjs.__fireBulletExtension;", + "", + "rotateObjectToFaceSameWayAsCamera(object);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "DefineHelperClasses" + }, + { + "functionName": "RotateObjectToFaceSameWayAsCamera" + } + ] + }, + "eventsBasedBehaviors": [ + { + "description": "Fire bullets with built-in cooldown, ammo, reloading, and overheating. Once added to your object that must shoot, use the behavior actions to fire another object as a bullet. These actions check all constraints internally (can be called without conditions, they will only fire when ready) and will make the bullet move (using a permanent force).", + "fullName": "Fire bullets", + "helpPath": "", + "iconUrl": "", + "name": "FireBullet", + "objectType": "", + "previewIconUrl": "", + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onCreated", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ResetObjectTimer" + }, + "parameters": [ + "Object", + "\"__FireBullet.FiringCooldown\"" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AmmoQuantity", + "=", + "StartingAmmo" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ShotsBeforeNextReload", + "=", + "ShotsPerReload" + ] + }, + { + "type": { + "value": "FireBullet::DefineHelperClasses" + }, + "parameters": [ + "", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const { CameraLocalBasis, ObjectLocalBasis } = gdjs.__fireBulletExtension;\r", + "const object = objects[0];\r", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));\r", + "behavior.__fireBulletExtension = {\r", + " cameraLocalBasis: new CameraLocalBasis(object),\r", + " objectLocalBasis: new ObjectLocalBasis(object)\r", + "};" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "doStepPreEvents", + "sentence": "", + "events": [ + { + "colorB": 224, + "colorG": 16, + "colorR": 189, + "creationTime": 0, + "name": "Take a shot (if triggered)", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Creators can use the \"FireBullet\" action multiple times in a frame and it will be counted as a single \"shot\"." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "HasJustFired", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "HasJustFired", + "False", + "" + ] + }, + { + "type": { + "value": "ResetObjectTimer" + }, + "parameters": [ + "Object", + "\"__FireBullet.FiringCooldown\"" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TotalShotsFired", + "+", + "1" + ] + } + ], + "events": [ + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Ammo", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanVariable" + }, + "parameters": [ + "UnlimitedAmmo", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AmmoQuantity", + "=", + "max(0, AmmoQuantity - 1)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "ShotsPerReload", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ShotsBeforeNextReload", + "-", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "AutomaticReloading", + "True", + "" + ] + }, + { + "type": { + "value": "FireBullet::FireBullet::IsReloadNeeded" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "inverted": true, + "value": "FireBullet::FireBullet::IsReloadInProgress" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::ReloadAmmo" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Overheat", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "HeatIncreasePerShot", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "HeatLevel", + "+", + "HeatIncreasePerShot" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "OverheatDuration", + ">", + "0" + ] + }, + { + "type": { + "value": "FireBullet::FireBullet::IsOverheated" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ResetObjectTimer" + }, + "parameters": [ + "Object", + "\"__FireBullet.OverheatDuration\"" + ] + } + ] + } + ] + } + ], + "parameters": [] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Reload", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Detect when reload is completed" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "FireBullet::FireBullet::IsReloadInProgress" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "value": "CompareObjectTimer" + }, + "parameters": [ + "Object", + "\"__FireBullet.ReloadingTimer\"", + ">=", + "ReloadDuration" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TotalReloadsCompleted", + "+", + "1" + ] + }, + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "ReloadInProgress", + "False", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "FireBullet::FireBullet::IsUnlimitedAmmo" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ShotsBeforeNextReload", + "=", + "ShotsPerReload" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Only reload the amount of ammo available" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "FireBullet::FireBullet::IsUnlimitedAmmo" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ShotsBeforeNextReload", + "=", + "min(ShotsPerReload, AmmoQuantity)" + ] + } + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Cooling", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "HeatLevel", + ">", + "0" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "ExponentialCoolingRate", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "HeatLevel", + "=", + "max(0, HeatLevel - TimeDelta() * ExponentialCoolingRate * HeatLevel)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "LinearCoolingRate", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "HeatLevel", + "=", + "max(0, HeatLevel - TimeDelta() * LinearCoolingRate)" + ] + } + ] + } + ] + } + ], + "parameters": [] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Fire bullets toward an object at a specified speed. Call this continuously, the action checks readiness internally — no extra timer or check needed.", + "fullName": "Fire bullets toward an object", + "functionType": "Action", + "name": "FireTowardObject", + "sentence": "Fire _PARAM4_ from _PARAM0_ (if ready), at position _PARAM2_; _PARAM3_, toward _PARAM5_ with speed _PARAM6_ px/s", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::Fire" + }, + "parameters": [ + "Object", + "Behavior", + "XPosition", + "YPosition", + "Bullet", + "Object.AngleToObject(TargetObject)", + "Speed", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "X position, where to create the bullet", + "name": "XPosition", + "type": "expression" + }, + { + "description": "Y position, where to create the bullet", + "name": "YPosition", + "type": "expression" + }, + { + "description": "The bullet object", + "name": "Bullet", + "type": "objectListOrEmptyIfJustDeclared" + }, + { + "description": "Target object", + "name": "TargetObject", + "type": "objectList" + }, + { + "description": "Speed of the bullet, in pixels per second", + "name": "Speed", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Fire bullets toward a position at a specified speed. Call this continuously, the action checks readiness internally — no extra timer or check needed.", + "fullName": "Fire bullets toward a position", + "functionType": "Action", + "name": "FireTowardPosition", + "sentence": "Fire _PARAM4_ from _PARAM0_ (if ready), at position _PARAM2_; _PARAM3_, toward position _PARAM5_;_PARAM6_ with speed _PARAM7_ px/s", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::Fire" + }, + "parameters": [ + "Object", + "Behavior", + "XPosition", + "YPosition", + "Bullet", + "Object.AngleToPosition(TargetXPosition, TargetYPosition)", + "Speed", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "X position, where to create the bullet", + "name": "XPosition", + "type": "expression" + }, + { + "description": "Y position, where to create the bullet", + "name": "YPosition", + "type": "expression" + }, + { + "description": "The bullet object", + "name": "Bullet", + "type": "objectListOrEmptyIfJustDeclared" + }, + { + "description": "Target X position", + "name": "TargetXPosition", + "type": "expression" + }, + { + "description": "Target Y position", + "name": "TargetYPosition", + "type": "expression" + }, + { + "description": "Speed of the bullet, in pixels per second", + "name": "Speed", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Fire bullets in the direction of a given angle at a specified speed. Call this continuously, the action checks readiness internally — no extra timer or check needed.", + "fullName": "Fire bullets toward an angle", + "functionType": "Action", + "name": "Fire", + "sentence": "Fire _PARAM4_ from _PARAM0_ (if ready), at position _PARAM2_; _PARAM3_, toward angle _PARAM5_ and speed _PARAM6_ px/s", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "FireBullet::FireBullet::IsReadyToShoot" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "HasJustFired", + "True", + "" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "BulletQuantity", + "=", + "1" + ] + } + ], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::FireSingleBullet" + }, + "parameters": [ + "Object", + "Behavior", + "XPosition", + "YPosition", + "Bullet", + "Angle", + "Speed", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "BulletQuantity", + ">", + "1" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Repeat", + "repeatExpression": "BulletQuantity", + "conditions": [], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "FireBullet::FireBullet::FiringArc" + }, + "parameters": [ + "Object", + "Behavior", + "!=", + "360", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "MultiShotAngle", + "=", + "Angle + lerp(-FiringArc / 2, FiringArc / 2, BulletIndex / (BulletQuantity - 1)) " + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "When firing in a full circle, prevent first and last bullet from using the same angle" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "FireBullet::FireBullet::FiringArc" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "360", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "MultiShotAngle", + "=", + "Angle + lerp(-FiringArc / 2, FiringArc / 2, BulletIndex / BulletQuantity) " + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::FireSingleBullet" + }, + "parameters": [ + "Object", + "Behavior", + "XPosition", + "YPosition", + "Bullet", + "MultiShotAngle", + "Speed", + "" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "BulletIndex", + "+", + "1" + ] + } + ] + } + ] + } + ], + "variables": [ + { + "folded": true, + "name": "MultiShotAngle", + "type": "number", + "value": 0 + }, + { + "name": "BulletIndex", + "type": "number", + "value": 0 + } + ] + } + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "X position, where to create the bullet", + "name": "XPosition", + "type": "expression" + }, + { + "description": "Y position, where to create the bullet", + "name": "YPosition", + "type": "expression" + }, + { + "description": "The bullet object", + "name": "Bullet", + "type": "objectListOrEmptyIfJustDeclared" + }, + { + "description": "Angle of the bullet, in degrees", + "name": "Angle", + "type": "expression" + }, + { + "description": "Speed of the bullet, in pixels per second", + "name": "Speed", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Fire a single bullet. This is only meant to be used inside the \"Fire bullet\" action.", + "fullName": "Fire a single bullet", + "functionType": "Action", + "group": "Firing", + "name": "FireSingleBullet", + "private": true, + "sentence": "Fire a single bullet _PARAM4_ from _PARAM0_, at position _PARAM2_; _PARAM3_, with angle _PARAM5_ and speed _PARAM6_ px/s", + "events": [ + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Fire a single bullet", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Create bullet" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Create" + }, + "parameters": [ + "", + "Bullet", + "XPosition", + "YPosition", + "BulletLayer" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Move bullet (apply angle and bullet speed variances)" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "RandomizedAngle", + "=", + "Angle + RandomInRange(-AngleVariance, AngleVariance)" + ] + }, + { + "type": { + "value": "AddForceAL" + }, + "parameters": [ + "Bullet", + "RandomizedAngle", + "Speed + RandomInRange(-BulletSpeedVariance, BulletSpeedVariance)", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Rotate newly created bullet, if needed" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "RotateBullet", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetAngle" + }, + "parameters": [ + "Bullet", + "=", + "RandomizedAngle" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Update statistics" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TotalBulletsCreated", + "+", + "1" + ] + } + ] + } + ], + "parameters": [] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "X position, where to create the bullet", + "name": "XPosition", + "type": "expression" + }, + { + "description": "Y position, where to create the bullet", + "name": "YPosition", + "type": "expression" + }, + { + "description": "The bullet object", + "name": "Bullet", + "type": "objectListOrEmptyIfJustDeclared" + }, + { + "description": "Angle of the bullet, in degrees", + "name": "Angle", + "type": "expression" + }, + { + "description": "Speed of the bullet, in pixels per second", + "name": "Speed", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Reload ammo.", + "fullName": "Reload ammo", + "functionType": "Action", + "name": "ReloadAmmo", + "sentence": "Reload ammo on _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "FireBullet::FireBullet::IsOutOfAmmo" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "ReloadInProgress", + "True", + "" + ] + }, + { + "type": { + "value": "ResetObjectTimer" + }, + "parameters": [ + "Object", + "\"__FireBullet.ReloadingTimer\"" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the object has just fired something.", + "fullName": "Has just fired", + "functionType": "Condition", + "group": "Firing", + "name": "HasJustFired", + "sentence": "_PARAM0_ has just fired", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "HasJustFired", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if bullet rotates to match trajectory.", + "fullName": "Is bullet rotation enabled", + "functionType": "Condition", + "group": "Firing", + "name": "BulletRotationEnabled", + "sentence": "Bullet rotation enabled on _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "RotateBullet", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the firing arc (in degrees) where bullets are shot. Bullets are evenly spaced out inside the firing arc.", + "fullName": "Firing arc", + "functionType": "ExpressionAndCondition", + "group": "Multi-Fire", + "name": "FiringArc", + "sentence": "the firing arc", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "FiringArc" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "FiringArc", + "group": "Multi-Fire", + "name": "SetFiringArcOp", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "FiringArc", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Firing arc (degrees) Range: 0 to 360", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the firing arc (in degrees) where bullets will be shot. Bullets will be evenly spaced out inside the firing arc.", + "fullName": "Set firing arc (deprecated)", + "functionType": "Action", + "group": "Multi-Fire", + "name": "SetFiringArc", + "private": true, + "sentence": "Set firing arc of _PARAM0_ to _PARAM2_ degrees", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::SetFiringArcOp" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "Value", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Firing arc (degrees) Range: 0 to 360", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the angle variance (in degrees) applied to each bullet.", + "fullName": "Angle variance", + "functionType": "ExpressionAndCondition", + "group": "Firing variance", + "name": "AngleVariance", + "sentence": "the angle variance", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "AngleVariance" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "AngleVariance", + "group": "Firing variance", + "name": "SetAngleVarianceOp", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AngleVariance", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Angle variance (degrees) Range: 0 to 180", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the angle variance (in degrees) applied to each bullet.", + "fullName": "Set angle variance (deprecated)", + "functionType": "Action", + "group": "Firing", + "name": "SetAngleVariance", + "private": true, + "sentence": "Set angle variance of _PARAM0_ to _PARAM2_ degrees", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::SetAngleVarianceOp" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "Value", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Angle variance (degrees) Range: 0 to 180", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the bullet speed variance (pixels per second) applied to each bullet.", + "fullName": "Bullet speed variance", + "functionType": "ExpressionAndCondition", + "group": "Firing variance", + "name": "BulletSpeedVariance", + "sentence": "the bullet speed variance", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "BulletSpeedVariance" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "BulletSpeedVariance", + "group": "Firing variance", + "name": "SetBulletSpeedVarianceOp", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "BulletSpeedVariance", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Angle variance (degrees) Range: 0 to 180", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the speed variance (pixels per second) applied to each bullet.", + "fullName": "Set bullet speed variance (deprecated)", + "functionType": "Action", + "group": "Multi-Fire", + "name": "SetBulletSpeedVariance", + "private": true, + "sentence": "Set bullet speed variance of _PARAM0_ to _PARAM2_ pixels per second", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::SetBulletSpeedVarianceOp" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "Value", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Angle variance (degrees) Range: 0 to 180", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the number of bullets shot every time the \"fire bullet\" action is used.", + "fullName": "Bullets per shot", + "functionType": "ExpressionAndCondition", + "group": "Multi-Fire", + "name": "BulletQuantity", + "sentence": "the number of bullets per shot", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "BulletQuantity" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "BulletQuantity", + "group": "Multi-Fire", + "name": "SetBulletQuantityOp", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "BulletQuantity", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Bullets", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the number of bullets shot every time the \"fire bullet\" action is used.", + "fullName": "Set number of bullets per shot (deprecated)", + "functionType": "Action", + "group": "Multi-Fire", + "name": "SetBulletQuantity", + "private": true, + "sentence": "Set number of bullets per shot of _PARAM0_ to _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::SetBulletQuantityOp" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "Value", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Bullets", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the layer that bullets are created on.", + "fullName": "Set bullet layer", + "functionType": "Action", + "group": "Firing", + "name": "SetBulletLayer", + "sentence": "Set the layer used to create bullets fired by _PARAM0_ to _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "BulletLayer", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Layer", + "name": "Value", + "type": "layer" + } + ], + "objectGroups": [] + }, + { + "description": "Enable bullet rotation.", + "fullName": "Enable (or disable) bullet rotation", + "functionType": "Action", + "group": "Firing", + "name": "SetRotateBullet", + "sentence": "Enable bullet rotation on _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "RotateBullet", + "False", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "RotateBullet", + "True", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "defaultValue": "yes", + "description": "Rotate bullet to match trajetory", + "name": "Value", + "optional": true, + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "Enable unlimited ammo.", + "fullName": "Enable (or disable) unlimited ammo", + "functionType": "Action", + "group": "Ammo", + "name": "SetUnlimitedAmmo", + "sentence": "Enable unlimited ammo on _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "UnlimitedAmmo", + "False", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "UnlimitedAmmo", + "True", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "defaultValue": "yes", + "description": "Unlimited ammo", + "name": "Value", + "optional": true, + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "the firing cooldown (in seconds) also known as rate of fire.", + "fullName": "Firing cooldown", + "functionType": "ExpressionAndCondition", + "group": "Firing", + "name": "Cooldown", + "sentence": "the firing cooldown", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "FireCooldown" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Cooldown", + "group": "Firing", + "name": "SetCooldownOp", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "FireCooldown", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Cooldown in seconds", + "name": "NewCooldown", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the firing cooldown, which changes the rate of fire.", + "fullName": "Set firing cooldown (deprecated)", + "functionType": "Action", + "group": "Firing", + "name": "SetCooldown", + "private": true, + "sentence": "Set the fire rate of _PARAM0_ to _PARAM2_ seconds", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::SetCooldownOp" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "Value", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Cooldown in seconds", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the reload duration (in seconds).", + "fullName": "Reload duration", + "functionType": "ExpressionAndCondition", + "group": "Reload", + "name": "ReloadDuration", + "sentence": "the reload duration", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ReloadDuration" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "ReloadDuration", + "group": "Reload", + "name": "SetReloadDurationOp", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ReloadDuration", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Reload duration (seconds)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the duration to reload ammo.", + "fullName": "Set reload duration (deprecated)", + "functionType": "Action", + "group": "Reload", + "name": "SetReloadDuration", + "private": true, + "sentence": "Set the reload duration of _PARAM0_ to _PARAM2_ seconds", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::SetReloadDurationOp" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "Value", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Reload duration (seconds)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the overheat duration (in seconds). When an object is overheated, it can't fire for this duration.", + "fullName": "Overheat duration", + "functionType": "ExpressionAndCondition", + "group": "Overheat", + "name": "OverheatDuration", + "sentence": "the overheat duration", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "OverheatDuration" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "OverheatDuration", + "group": "Overheat", + "name": "SetOverheatDurationOp", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "OverheatDuration", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Overheat duration (seconds)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the duration after becoming overheated.", + "fullName": "Set overheat duration (deprecated)", + "functionType": "Action", + "group": "Overheat", + "name": "SetOverheatDuration", + "private": true, + "sentence": "Set the overheat duration of _PARAM0_ to _PARAM2_ seconds", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::SetOverheatDurationOp" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "Value", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Overheat duration (seconds)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the ammo quantity.", + "fullName": "Ammo quantity", + "functionType": "ExpressionAndCondition", + "group": "Ammo", + "name": "AmmoQuantity", + "sentence": "the ammo quantity", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "AmmoQuantity" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "AmmoQuantity", + "group": "Ammo", + "name": "SetAmmoQuantityOp", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AmmoQuantity", + "=", + "max(0, Value)" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Ammo", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the quantity of ammo.", + "fullName": "Set ammo quantity (deprecated)", + "functionType": "Action", + "group": "Ammo", + "name": "SetAmmoQuantity", + "private": true, + "sentence": "Set the ammo quantity of _PARAM0_ to _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::SetAmmoQuantityOp" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "max(0, Value)", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Ammo", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the heat increase per shot.", + "fullName": "Heat increase per shot", + "functionType": "ExpressionAndCondition", + "group": "Overheat", + "name": "HeatIncreasePerShot", + "sentence": "the heat increase per shot", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "HeatIncreasePerShot" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "HeatIncreasePerShot", + "group": "Overheat", + "name": "SetHeatPerShotOp", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "HeatIncreasePerShot", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Heat increase per shot (Range: 0 to 1)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the heat increase per shot.", + "fullName": "Set heat increase per shot (deprecated)", + "functionType": "Action", + "group": "Overheat", + "name": "SetHeatPerShot", + "private": true, + "sentence": "Set the heat increase of _PARAM0_ to _PARAM2_ per shot", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::SetHeatPerShotOp" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "Value", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Heat increase per shot (Range: 0 to 1)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the max ammo.", + "fullName": "Max ammo", + "functionType": "ExpressionAndCondition", + "group": "Ammo", + "name": "MaxAmmo", + "sentence": "the max ammo", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "MaxAmmo" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "MaxAmmo", + "group": "Ammo", + "name": "SetMaxAmmoOp", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "MaxAmmo", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "MaxAmmo", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AmmoQuantity", + "=", + "min(MaxAmmo, AmmoQuantity)" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Max ammo", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the max ammo.", + "fullName": "Set max ammo (deprecated)", + "functionType": "Action", + "group": "Ammo", + "name": "SetMaxAmmo", + "private": true, + "sentence": "Set the max ammo of _PARAM0_ to _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::SetMaxAmmoOp" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "Value", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Max ammo", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Reset total shots fired.", + "fullName": "Reset total shots fired", + "functionType": "Action", + "group": "Stats", + "name": "ResetTotalShotsFired", + "sentence": "Reset total shots fired by _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TotalShotsFired", + "=", + "0" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Reset total bullets created.", + "fullName": "Reset total bullets created", + "functionType": "Action", + "group": "Stats", + "name": "ResetTotalBulletsCreated", + "sentence": "Reset total bullets created by _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TotalBulletsCreated", + "=", + "0" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Reset total reloads completed.", + "fullName": "Reset total reloads completed", + "functionType": "Action", + "group": "Stats", + "name": "ResetTotalReloadsCompleted", + "sentence": "Reset total reloads completed by _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "TotalReloadsCompleted", + "=", + "0" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the number of shots per reload.", + "fullName": "Shots per reload", + "functionType": "ExpressionAndCondition", + "group": "Reload", + "name": "ShotsPerReload", + "sentence": "the shots per reload", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ShotsPerReload" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "ShotsPerReload", + "group": "Reload", + "name": "SetShotsPerReloadOp", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ShotsPerReload", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "ShotsBeforeNextReload", + ">", + "ShotsPerReload" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ShotsBeforeNextReload", + "=", + "ShotsPerReload" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Shots per reload", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the number of shots per reload.", + "fullName": "Set shots per reload (deprecated)", + "functionType": "Action", + "group": "Reload", + "name": "SetShotsPerReload", + "private": true, + "sentence": "Set the shots per reload of _PARAM0_ to _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::SetShotsPerReloadOp" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "Value", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Shots per reload", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Enable (or disable) automatic reloading.", + "fullName": "Enable (or disable) automatic reloading", + "functionType": "Action", + "group": "Reload", + "name": "SetAutomaticReload", + "sentence": "Enable automatic reloading on _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "AutomaticReloading", + "False", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "AutomaticReloading", + "True", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "defaultValue": "yes", + "description": "Enable automatic reloading", + "name": "Value", + "optional": true, + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "the linear cooling rate (per second).", + "fullName": "Linear cooling rate", + "functionType": "ExpressionAndCondition", + "group": "Overheat", + "name": "LinearCoolingRate", + "sentence": "the linear cooling rate", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "LinearCoolingRate" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "LinearCoolingRate", + "group": "Overheat", + "name": "SetLinearCoolingRateOp", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "LinearCoolingRate", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Heat cooling rate (per second)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the linear rate of cooling.", + "fullName": "Set linear cooling rate (deprecated)", + "functionType": "Action", + "group": "Overheat", + "name": "SetLinearCoolingRate", + "private": true, + "sentence": "Set the linear cooling rate of _PARAM0_ to _PARAM2_ per second", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::SetLinearCoolingRateOp" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "Value", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Heat cooling rate (per second)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the exponential cooling rate, per second.", + "fullName": "Exponential cooling rate", + "functionType": "ExpressionAndCondition", + "group": "Overheat", + "name": "ExponentialCoolingRate", + "sentence": "the exponential cooling rate", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ExponentialCoolingRate" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "ExponentialCoolingRate", + "group": "Overheat", + "name": "SetExponentialCoolingRateOp", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ExponentialCoolingRate", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Exponential cooling rate", + "name": "Value", + "supplementaryInformation": "[\"Exponential\",\"Linear\"]", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the exponential rate of cooling.", + "fullName": "Set exponential cooling rate (deprecated)", + "functionType": "Action", + "group": "Overheat", + "name": "SetExponentialCoolingRate", + "private": true, + "sentence": "Set the exponential cooling rate of _PARAM0_ to _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::SetExponentialCoolingRateOp" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "Value", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Exponential cooling rate", + "name": "Value", + "supplementaryInformation": "[\"Exponential\",\"Linear\"]", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Increase ammo quantity.", + "fullName": "Increase ammo", + "functionType": "Action", + "name": "IncreaseAmmo", + "sentence": "Increase ammo of _PARAM0_ by _PARAM2_ shots", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AmmoQuantity", + "+", + "AmmoGained" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "If Max Ammo is set, do not exceed the value" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "MaxAmmo", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "AmmoQuantity", + "=", + "min(MaxAmmo, AmmoQuantity)" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "FireBullet::FireBullet::IsReloadNeeded" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "AutomaticReloading", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "FireBullet::FireBullet::ReloadAmmo" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Ammo gained", + "name": "AmmoGained", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Layer that bullets are created on.", + "fullName": "Bullet layer", + "functionType": "StringExpression", + "group": "Multi-Fire", + "name": "BulletLayer", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnString" + }, + "parameters": [ + "BulletLayer" + ] + } + ] + } + ], + "expressionType": { + "type": "layer" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the heat level (range: 0 to 1).", + "fullName": "Heat level", + "functionType": "ExpressionAndCondition", + "group": "Overheat", + "name": "HeatLevel", + "sentence": "the heat level", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "min(1, HeatLevel)" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Total shots fired (multi-bullet shots are considered one shot).", + "fullName": "Shots fired", + "functionType": "Expression", + "group": "Stats", + "name": "TotalShotsFired", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "TotalShotsFired" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Total bullets created.", + "fullName": "Bullets created", + "functionType": "Expression", + "group": "Stats", + "name": "TotalBulletsCreated", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "TotalBulletsCreated" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Reloads completed.", + "fullName": "Reloads completed", + "functionType": "Expression", + "group": "Stats", + "name": "TotalReloadsCompleted", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "TotalReloadsCompleted" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the remaining shots before the next reload is required.", + "fullName": "Shots before next reload", + "functionType": "ExpressionAndCondition", + "group": "Reload", + "name": "ShotsBeforeNextReload", + "sentence": "the remaining shots (before the next reload)", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ShotsBeforeNextReload" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the remaining duration before the cooldown will permit a bullet to be fired, in seconds.", + "fullName": "Duration before cooldown end", + "functionType": "ExpressionAndCondition", + "group": "Firing", + "name": "CooldownTimeLeft", + "sentence": "the remaining duration before the cooldown end", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "max(0, FireCooldown - Object.ObjectTimerElapsedTime(\"__FireBullet.FiringCooldown\"))" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the remaining duration before the overheat penalty ends, in seconds.", + "fullName": "Duration before overheat end", + "functionType": "ExpressionAndCondition", + "group": "Overheat", + "name": "OverheatTimeLeft", + "sentence": "the remaining duration before the overheat end", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CompareObjectTimer" + }, + "parameters": [ + "Object", + "\"__FireBullet.OverheatDuration\"", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "max(0, OverheatDuration - Object.ObjectTimerElapsedTime(\"__FireBullet.OverheatDuration\"))" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the remaining duration before the reload finishes, in seconds.", + "fullName": "Duration before the reload finishes", + "functionType": "ExpressionAndCondition", + "group": "Reload", + "name": "ReloadTimeLeft", + "sentence": "the remaining duration before the reload finishes", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CompareObjectTimer" + }, + "parameters": [ + "Object", + "\"__FireBullet.ReloadingTimer\"", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "max(0, ReloadDuration - Object.ObjectTimerElapsedTime(\"__FireBullet.ReloadingTimer\"))" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if object is currently performing an ammo reload.", + "fullName": "Is ammo reloading in progress", + "functionType": "Condition", + "group": "Reload", + "name": "IsReloadInProgress", + "sentence": "_PARAM0_ is reloading ammo", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "False" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "ReloadInProgress", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if object is ready to shoot.", + "fullName": "Is ready to shoot", + "functionType": "Condition", + "group": "Firing", + "name": "IsReadyToShoot", + "sentence": "_PARAM0_ is ready to shoot", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "False" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "HasJustFired", + "True", + "" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::And" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "BehaviorActivated" + }, + "parameters": [ + "Object", + "Behavior" + ] + }, + { + "type": { + "inverted": true, + "value": "FireBullet::FireBullet::IsOutOfAmmo" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "inverted": true, + "value": "FireBullet::FireBullet::IsReloadNeeded" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "inverted": true, + "value": "FireBullet::FireBullet::IsReloadInProgress" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "inverted": true, + "value": "FireBullet::FireBullet::IsFiringCooldownActive" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "inverted": true, + "value": "FireBullet::FireBullet::IsOverheated" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ] + } + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if automatic reloading is enabled.", + "fullName": "Is automatic reloading enabled", + "functionType": "Condition", + "group": "Reload", + "name": "IsAutomaticReloadingEnabled", + "sentence": "Automatic reloading is enabled on_PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "False" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "AutomaticReloading", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if ammo is unlimited.", + "fullName": "Is ammo unlimited", + "functionType": "Condition", + "group": "Ammo", + "name": "IsUnlimitedAmmo", + "sentence": "_PARAM0_ has unlimited ammo", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "False" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "UnlimitedAmmo", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if object has no ammo available.", + "fullName": "Is out of ammo", + "functionType": "Condition", + "group": "Ammo", + "name": "IsOutOfAmmo", + "sentence": "_PARAM0_ is out of ammo", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "False" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "FireBullet::FireBullet::IsUnlimitedAmmo" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "AmmoQuantity", + "<=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if object needs to reload ammo.", + "fullName": "Is a reload needed", + "functionType": "Condition", + "group": "Reload", + "name": "IsReloadNeeded", + "sentence": "_PARAM0_ needs to reload ammo", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "False" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Shots per reload must not be \"0\"" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "ShotsPerReload", + ">", + "0" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "ShotsBeforeNextReload", + "=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if object is overheated.", + "fullName": "Is overheated", + "functionType": "Condition", + "group": "Overheat", + "name": "IsOverheated", + "sentence": "_PARAM0_ is overheated", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "False" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "HeatLevel", + ">=", + "1" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Object.Behavior::OverheatTimeLeft()", + ">", + "0" + ] + } + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if firing cooldown is active.", + "fullName": "Is firing cooldown active", + "functionType": "Condition", + "group": "Firing", + "name": "IsFiringCooldownActive", + "sentence": "Firing cooldown is active on _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "False" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Object.Behavior::CooldownTimeLeft()", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Fire bullets from the object at a specified speed. Call this continuously, the action checks readiness internally — no extra timer or check needed.", + "fullName": "Fire bullets from 3D object", + "functionType": "Action", + "name": "FireForwardObject3D", + "sentence": "Fire _PARAM6_ from _PARAM0_ (if ready) with offset _PARAM3_ ; _PARAM4_ ; _PARAM5_ at speed _PARAM9_ px/s", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "FireBullet::FireBullet::IsReadyToShoot" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "HasJustFired", + "True", + "" + ] + }, + { + "type": { + "value": "Create" + }, + "parameters": [ + "", + "Bullet", + "0", + "0", + "Object.Layer()" + ] + }, + { + "type": { + "value": "SetCenter" + }, + "parameters": [ + "Bullet", + "=", + "Object.CenterX()", + "=", + "Object.CenterY()" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetCenterZ" + }, + "parameters": [ + "Bullet", + "Object3D2", + "=", + "Object.Object3D::CenterZ()" + ] + }, + { + "type": { + "value": "FireBullet::FireBullet::UpdateObjectLocalBasis" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "value": "SetX" + }, + "parameters": [ + "Bullet", + "+", + "Object.Behavior::WorldOffsetX(OffsetX, OffsetY, OffsetZ)" + ] + }, + { + "type": { + "value": "SetY" + }, + "parameters": [ + "Bullet", + "+", + "Object.Behavior::WorldOffsetY(OffsetX, OffsetY, OffsetZ)" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetZ" + }, + "parameters": [ + "Bullet", + "Object3D2", + "+", + "Object.Behavior::WorldOffsetZ(OffsetX, OffsetY, OffsetZ)" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "Bullet", + "Physics3D", + "=", + "Speed * Object.Behavior::ForwardX()" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "Bullet", + "Physics3D", + "=", + "Speed * Object.Behavior::ForwardY()" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityZ" + }, + "parameters": [ + "Bullet", + "Physics3D", + "=", + "Speed * Object.Behavior::ForwardZ()" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "RotateBullet", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetAngle" + }, + "parameters": [ + "Bullet", + "=", + "Object.Angle()" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetRotationY" + }, + "parameters": [ + "Bullet", + "Object3D2", + "=", + "Object.Object3D::RotationY()" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetRotationX" + }, + "parameters": [ + "Bullet", + "Object3D2", + "=", + "Object.Object3D::RotationX()" + ] + } + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + }, + { + "description": "Forward offset", + "longDescription": "Offset on local X axis of the object.", + "name": "OffsetX", + "type": "expression" + }, + { + "description": "Offset to the right", + "longDescription": "Offset on local Y axis of the object.", + "name": "OffsetY", + "type": "expression" + }, + { + "description": "Upward offset", + "longDescription": "Offset on local Z axis of the object.", + "name": "OffsetZ", + "type": "expression" + }, + { + "description": "The bullet object", + "name": "Bullet", + "type": "objectListOrEmptyIfJustDeclared" + }, + { + "description": "3D capability", + "name": "Object3D2", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + }, + { + "description": "3D physics engine", + "name": "Physics3D", + "supplementaryInformation": "Physics3D::Physics3DBehavior", + "type": "behavior" + }, + { + "description": "Speed of the bullet, in pixels per second", + "name": "Speed", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "fullName": "Update camera local basis", + "functionType": "Action", + "group": "3D Helpers", + "name": "UpdateCameraLocalBasis", + "private": true, + "sentence": "Update camera local basis of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "const { cameraLocalBasis } = behavior.__fireBulletExtension;", + "cameraLocalBasis.update();", + "console.log(cameraLocalBasis.forward, cameraLocalBasis.up, cameraLocalBasis.right);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "World offset X", + "functionType": "Expression", + "group": "3D Helpers", + "name": "WorldOffsetX", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "const { objectLocalBasis } = behavior.__fireBulletExtension;", + "", + "const offsetX = eventsFunctionContext.getArgument(\"OffsetX\");", + "const offsetY = eventsFunctionContext.getArgument(\"OffsetY\");", + "const offsetZ = eventsFunctionContext.getArgument(\"OffsetZ\");", + "", + "eventsFunctionContext.returnValue = objectLocalBasis.getWorldOffsetX(offsetX, offsetY, offsetZ);", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Local offset X", + "name": "OffsetX", + "type": "expression" + }, + { + "description": "Local offset Y", + "name": "OffsetY", + "type": "expression" + }, + { + "description": "Local offset Z", + "name": "OffsetZ", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "fullName": "World offset Y", + "functionType": "Expression", + "group": "3D Helpers", + "name": "WorldOffsetY", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "const { objectLocalBasis } = behavior.__fireBulletExtension;", + "", + "const offsetX = eventsFunctionContext.getArgument(\"OffsetX\");", + "const offsetY = eventsFunctionContext.getArgument(\"OffsetY\");", + "const offsetZ = eventsFunctionContext.getArgument(\"OffsetZ\");", + "", + "eventsFunctionContext.returnValue = objectLocalBasis.getWorldOffsetY(offsetX, offsetY, offsetZ);", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Local offset X", + "name": "OffsetX", + "type": "expression" + }, + { + "description": "Local offset Y", + "name": "OffsetY", + "type": "expression" + }, + { + "description": "Local offset Z", + "name": "OffsetZ", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "fullName": "World offset Z", + "functionType": "Expression", + "group": "3D Helpers", + "name": "WorldOffsetZ", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "const { objectLocalBasis } = behavior.__fireBulletExtension;", + "", + "const offsetX = eventsFunctionContext.getArgument(\"OffsetX\");", + "const offsetY = eventsFunctionContext.getArgument(\"OffsetY\");", + "const offsetZ = eventsFunctionContext.getArgument(\"OffsetZ\");", + "", + "eventsFunctionContext.returnValue = objectLocalBasis.getWorldOffsetZ(offsetX, offsetY, offsetZ);", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Local offset X", + "name": "OffsetX", + "type": "expression" + }, + { + "description": "Local offset Y", + "name": "OffsetY", + "type": "expression" + }, + { + "description": "Local offset Z", + "name": "OffsetZ", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "fullName": "Forward X", + "functionType": "Expression", + "group": "3D Helpers", + "name": "ForwardX", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "const { objectLocalBasis } = behavior.__fireBulletExtension;", + "", + "eventsFunctionContext.returnValue = objectLocalBasis.forward.x;", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "Forward Y", + "functionType": "Expression", + "group": "3D Helpers", + "name": "ForwardY", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "const { objectLocalBasis } = behavior.__fireBulletExtension;", + "", + "eventsFunctionContext.returnValue = objectLocalBasis.forward.y;", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "Forward Z", + "functionType": "Expression", + "group": "3D Helpers", + "name": "ForwardZ", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "const { objectLocalBasis } = behavior.__fireBulletExtension;", + "", + "eventsFunctionContext.returnValue = objectLocalBasis.forward.z;", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "Update object local basis", + "functionType": "Action", + "group": "3D Helpers", + "name": "UpdateObjectLocalBasis", + "private": true, + "sentence": "Update local basis of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "const { objectLocalBasis } = behavior.__fireBulletExtension;", + "objectLocalBasis.update();", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "Camera forward X", + "functionType": "Expression", + "group": "3D Helpers", + "name": "CameraForwardX", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "const { cameraLocalBasis } = behavior.__fireBulletExtension;", + "", + "eventsFunctionContext.returnValue = cameraLocalBasis.forward.x;", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "Camera forward Y", + "functionType": "Expression", + "group": "3D Helpers", + "name": "CameraForwardY", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "const { cameraLocalBasis } = behavior.__fireBulletExtension;", + "", + "eventsFunctionContext.returnValue = cameraLocalBasis.forward.y;", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "Camera forward Z", + "functionType": "Expression", + "group": "3D Helpers", + "name": "CameraForwardZ", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "const { cameraLocalBasis } = behavior.__fireBulletExtension;", + "", + "eventsFunctionContext.returnValue = cameraLocalBasis.forward.z;", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Fire bullets from the camera at a specified speed. Call this continuously, the action checks readiness internally — no extra timer or check needed.", + "fullName": "Fire bullets from 3D camera", + "functionType": "Action", + "name": "FireForwardCamera3D", + "sentence": "Fire _PARAM6_ from the camera of _PARAM0_ (if ready) with offset _PARAM3_ ; _PARAM4_ ; _PARAM5_ at speed _PARAM9_ px/s", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "FireBullet::FireBullet::IsReadyToShoot" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "HasJustFired", + "True", + "" + ] + }, + { + "type": { + "value": "Create" + }, + "parameters": [ + "", + "Bullet", + "0", + "0", + "Object.Layer()" + ] + }, + { + "type": { + "value": "SetCenter" + }, + "parameters": [ + "Bullet", + "=", + "CameraCenterX(Object.Layer())", + "=", + "CameraCenterY(Object.Layer())" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetCenterZ" + }, + "parameters": [ + "Bullet", + "Object3D2", + "=", + "Scene3D::CameraZ(Object.Layer())" + ] + }, + { + "type": { + "value": "FireBullet::FireBullet::UpdateCameraLocalBasis" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "value": "SetX" + }, + "parameters": [ + "Bullet", + "+", + "Object.Behavior::WorldCameraOffsetX(OffsetX, OffsetY, OffsetZ)" + ] + }, + { + "type": { + "value": "SetY" + }, + "parameters": [ + "Bullet", + "+", + "Object.Behavior::WorldCameraOffsetY(OffsetX, OffsetY, OffsetZ)" + ] + }, + { + "type": { + "value": "Scene3D::Base3DBehavior::SetZ" + }, + "parameters": [ + "Bullet", + "Object3D2", + "+", + "Object.Behavior::WorldCameraOffsetZ(OffsetX, OffsetY, OffsetZ)" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityX" + }, + "parameters": [ + "Bullet", + "Physics3D", + "=", + "Speed * Object.Behavior::CameraForwardX()" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityY" + }, + "parameters": [ + "Bullet", + "Physics3D", + "=", + "Speed * Object.Behavior::CameraForwardY()" + ] + }, + { + "type": { + "value": "Physics3D::Physics3DBehavior::SetLinearVelocityZ" + }, + "parameters": [ + "Bullet", + "Physics3D", + "=", + "Speed * Object.Behavior::CameraForwardZ()" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "RotateBullet", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "FireBullet::RotateObjectToFaceSameWayAsCamera" + }, + "parameters": [ + "", + "Bullet", + "Object3D2", + "" + ] + } + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + }, + { + "description": "Forward offset", + "longDescription": "Offset on local X axis of the camera.", + "name": "OffsetX", + "type": "expression" + }, + { + "description": "Offset to the right", + "longDescription": "Offset on local Y axis of the camera.", + "name": "OffsetY", + "type": "expression" + }, + { + "description": "Upward offset", + "longDescription": "Offset on local Z axis of the camera.", + "name": "OffsetZ", + "type": "expression" + }, + { + "description": "The bullet object", + "name": "Bullet", + "type": "objectListOrEmptyIfJustDeclared" + }, + { + "description": "3D capability", + "name": "Object3D2", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + }, + { + "description": "3D physics engine", + "name": "Physics3D", + "supplementaryInformation": "Physics3D::Physics3DBehavior", + "type": "behavior" + }, + { + "description": "Speed of the bullet, in pixels per second", + "name": "Speed", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "fullName": "World camera offset X", + "functionType": "Expression", + "group": "3D Helpers", + "name": "WorldCameraOffsetX", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "const { cameraLocalBasis } = behavior.__fireBulletExtension;", + "", + "const offsetX = eventsFunctionContext.getArgument(\"OffsetX\");", + "const offsetY = eventsFunctionContext.getArgument(\"OffsetY\");", + "const offsetZ = eventsFunctionContext.getArgument(\"OffsetZ\");", + "", + "eventsFunctionContext.returnValue = cameraLocalBasis.getWorldOffsetX(offsetX, offsetY, offsetZ);", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Local offset X", + "name": "OffsetX", + "type": "expression" + }, + { + "description": "Local offset Y", + "name": "OffsetY", + "type": "expression" + }, + { + "description": "Local offset Z", + "name": "OffsetZ", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "fullName": "World camera offset Y", + "functionType": "Expression", + "group": "3D Helpers", + "name": "WorldCameraOffsetY", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "const { cameraLocalBasis } = behavior.__fireBulletExtension;", + "", + "const offsetX = eventsFunctionContext.getArgument(\"OffsetX\");", + "const offsetY = eventsFunctionContext.getArgument(\"OffsetY\");", + "const offsetZ = eventsFunctionContext.getArgument(\"OffsetZ\");", + "", + "eventsFunctionContext.returnValue = cameraLocalBasis.getWorldOffsetY(offsetX, offsetY, offsetZ);", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Local offset X", + "name": "OffsetX", + "type": "expression" + }, + { + "description": "Local offset Y", + "name": "OffsetY", + "type": "expression" + }, + { + "description": "Local offset Z", + "name": "OffsetZ", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "fullName": "World camera offset Z", + "functionType": "Expression", + "group": "3D Helpers", + "name": "WorldCameraOffsetZ", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "const { cameraLocalBasis } = behavior.__fireBulletExtension;", + "", + "const offsetX = eventsFunctionContext.getArgument(\"OffsetX\");", + "const offsetY = eventsFunctionContext.getArgument(\"OffsetY\");", + "const offsetZ = eventsFunctionContext.getArgument(\"OffsetZ\");", + "", + "eventsFunctionContext.returnValue = cameraLocalBasis.getWorldOffsetZ(offsetX, offsetY, offsetZ);", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "FireBullet::FireBullet", + "type": "behavior" + }, + { + "description": "Local offset X", + "name": "OffsetX", + "type": "expression" + }, + { + "description": "Local offset Y", + "name": "OffsetY", + "type": "expression" + }, + { + "description": "Local offset Z", + "name": "OffsetZ", + "type": "expression" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onCreated" + }, + { + "functionName": "doStepPreEvents" + }, + { + "functionName": "FireTowardObject" + }, + { + "functionName": "FireTowardPosition" + }, + { + "functionName": "Fire" + }, + { + "functionName": "FireForwardObject3D" + }, + { + "functionName": "FireForwardCamera3D" + }, + { + "folderName": "3D Helpers", + "children": [ + { + "functionName": "UpdateCameraLocalBasis" + }, + { + "functionName": "CameraForwardX" + }, + { + "functionName": "CameraForwardY" + }, + { + "functionName": "CameraForwardZ" + }, + { + "functionName": "WorldCameraOffsetX" + }, + { + "functionName": "WorldCameraOffsetY" + }, + { + "functionName": "WorldCameraOffsetZ" + }, + { + "functionName": "UpdateObjectLocalBasis" + }, + { + "functionName": "ForwardX" + }, + { + "functionName": "ForwardY" + }, + { + "functionName": "ForwardZ" + }, + { + "functionName": "WorldOffsetX" + }, + { + "functionName": "WorldOffsetY" + }, + { + "functionName": "WorldOffsetZ" + } + ] + }, + { + "folderName": "Firing", + "children": [ + { + "functionName": "FireSingleBullet" + }, + { + "functionName": "HasJustFired" + }, + { + "functionName": "BulletRotationEnabled" + }, + { + "functionName": "SetAngleVariance" + }, + { + "functionName": "SetBulletLayer" + }, + { + "functionName": "SetRotateBullet" + }, + { + "functionName": "Cooldown" + }, + { + "functionName": "SetCooldownOp" + }, + { + "functionName": "SetCooldown" + }, + { + "functionName": "CooldownTimeLeft" + }, + { + "functionName": "IsReadyToShoot" + }, + { + "functionName": "IsFiringCooldownActive" + } + ] + }, + { + "functionName": "ReloadAmmo" + }, + { + "folderName": "Multi-Fire", + "children": [ + { + "functionName": "FiringArc" + }, + { + "functionName": "SetFiringArcOp" + }, + { + "functionName": "SetFiringArc" + }, + { + "functionName": "SetBulletSpeedVariance" + }, + { + "functionName": "BulletQuantity" + }, + { + "functionName": "SetBulletQuantityOp" + }, + { + "functionName": "SetBulletQuantity" + }, + { + "functionName": "BulletLayer" + } + ] + }, + { + "folderName": "Firing variance", + "children": [ + { + "functionName": "AngleVariance" + }, + { + "functionName": "SetAngleVarianceOp" + }, + { + "functionName": "BulletSpeedVariance" + }, + { + "functionName": "SetBulletSpeedVarianceOp" + } + ] + }, + { + "folderName": "Ammo", + "children": [ + { + "functionName": "SetUnlimitedAmmo" + }, + { + "functionName": "AmmoQuantity" + }, + { + "functionName": "SetAmmoQuantityOp" + }, + { + "functionName": "SetAmmoQuantity" + }, + { + "functionName": "MaxAmmo" + }, + { + "functionName": "SetMaxAmmoOp" + }, + { + "functionName": "SetMaxAmmo" + }, + { + "functionName": "IsUnlimitedAmmo" + }, + { + "functionName": "IsOutOfAmmo" + } + ] + }, + { + "folderName": "Reload", + "children": [ + { + "functionName": "ReloadDuration" + }, + { + "functionName": "SetReloadDurationOp" + }, + { + "functionName": "SetReloadDuration" + }, + { + "functionName": "ShotsPerReload" + }, + { + "functionName": "SetShotsPerReloadOp" + }, + { + "functionName": "SetShotsPerReload" + }, + { + "functionName": "SetAutomaticReload" + }, + { + "functionName": "ShotsBeforeNextReload" + }, + { + "functionName": "ReloadTimeLeft" + }, + { + "functionName": "IsReloadInProgress" + }, + { + "functionName": "IsAutomaticReloadingEnabled" + }, + { + "functionName": "IsReloadNeeded" + } + ] + }, + { + "folderName": "Overheat", + "children": [ + { + "functionName": "OverheatDuration" + }, + { + "functionName": "SetOverheatDurationOp" + }, + { + "functionName": "SetOverheatDuration" + }, + { + "functionName": "HeatIncreasePerShot" + }, + { + "functionName": "SetHeatPerShotOp" + }, + { + "functionName": "SetHeatPerShot" + }, + { + "functionName": "LinearCoolingRate" + }, + { + "functionName": "SetLinearCoolingRateOp" + }, + { + "functionName": "SetLinearCoolingRate" + }, + { + "functionName": "ExponentialCoolingRate" + }, + { + "functionName": "SetExponentialCoolingRateOp" + }, + { + "functionName": "SetExponentialCoolingRate" + }, + { + "functionName": "HeatLevel" + }, + { + "functionName": "OverheatTimeLeft" + }, + { + "functionName": "IsOverheated" + } + ] + }, + { + "folderName": "Stats", + "children": [ + { + "functionName": "ResetTotalShotsFired" + }, + { + "functionName": "ResetTotalBulletsCreated" + }, + { + "functionName": "ResetTotalReloadsCompleted" + }, + { + "functionName": "TotalShotsFired" + }, + { + "functionName": "TotalBulletsCreated" + }, + { + "functionName": "TotalReloadsCompleted" + } + ] + }, + { + "functionName": "IncreaseAmmo" + } + ] + }, + "propertyDescriptors": [ + { + "value": "0.1", + "type": "Number", + "unit": "Second", + "label": "Firing cooldown", + "description": "Objects cannot shoot while firing cooldown is active.", + "name": "FireCooldown" + }, + { + "value": "", + "type": "Boolean", + "label": "", + "hidden": true, + "name": "HasJustFired" + }, + { + "value": "true", + "type": "Boolean", + "label": "Rotate bullets to match their trajectory", + "name": "RotateBullet" + }, + { + "value": "45", + "type": "Number", + "unit": "DegreeAngle", + "label": "Firing arc", + "description": "Multi-Fire bullets will be evenly spaced inside the firing arc", + "group": "Multi-Fire", + "name": "FiringArc" + }, + { + "value": "1", + "type": "Number", + "label": "Number of bullets created at once", + "description": "Multi-Fire bullets will be evenly spaced inside the firing arc", + "group": "Multi-Fire", + "name": "BulletQuantity" + }, + { + "value": "0", + "type": "Number", + "unit": "DegreeAngle", + "label": "Angle variance", + "description": "Make imperfect aim (between 0 and 180 degrees).", + "group": "Firing variance", + "advanced": true, + "name": "AngleVariance" + }, + { + "value": "0", + "type": "Number", + "unit": "PixelSpeed", + "label": "Bullet speed variance", + "description": "Bullet speed will be adjusted by a random value within this range.", + "group": "Firing variance", + "advanced": true, + "name": "BulletSpeedVariance" + }, + { + "value": "0", + "type": "Number", + "label": "Ammo quantity (current)", + "hidden": true, + "name": "AmmoQuantity" + }, + { + "value": "0", + "type": "Number", + "label": "Shots per reload ", + "description": "Use 0 to disable reloading.", + "group": "Reload", + "advanced": true, + "name": "ShotsPerReload" + }, + { + "value": "1", + "type": "Number", + "unit": "Second", + "label": "Reloading duration", + "description": "Objects cannot shoot while reloading is in progress.", + "group": "Reload", + "advanced": true, + "name": "ReloadDuration" + }, + { + "value": "0", + "type": "Number", + "label": "Max ammo ", + "group": "Ammo", + "advanced": true, + "name": "MaxAmmo" + }, + { + "value": "0", + "type": "Number", + "label": "Shots before next reload", + "hidden": true, + "name": "ShotsBeforeNextReload" + }, + { + "value": "0", + "type": "Number", + "label": "Total shots fired", + "description": "Regardless of how many bullets are created, only 1 shot will be counted per frame", + "hidden": true, + "name": "TotalShotsFired" + }, + { + "value": "0", + "type": "Number", + "label": "Total bullets created", + "hidden": true, + "name": "TotalBulletsCreated" + }, + { + "value": "0", + "type": "Number", + "label": "Starting ammo", + "group": "Ammo", + "advanced": true, + "name": "StartingAmmo" + }, + { + "value": "0", + "type": "Number", + "label": "Total reloads completed", + "hidden": true, + "name": "TotalReloadsCompleted" + }, + { + "value": "true", + "type": "Boolean", + "label": "Unlimited ammo", + "group": "Ammo", + "advanced": true, + "name": "UnlimitedAmmo" + }, + { + "value": "", + "type": "Boolean", + "label": "", + "hidden": true, + "name": "ReloadInProgress" + }, + { + "value": "0", + "type": "Number", + "label": "Heat increase per shot (between 0 and 1)", + "description": " Object is overheated when Heat reaches 1.", + "group": "Overheat", + "advanced": true, + "name": "HeatIncreasePerShot" + }, + { + "value": "0", + "type": "Number", + "label": "Heat level (Range: 0 to 1)", + "hidden": true, + "name": "HeatLevel" + }, + { + "value": "true", + "type": "Boolean", + "label": "Reload automatically", + "group": "Reload", + "advanced": true, + "name": "AutomaticReloading" + }, + { + "value": "0", + "type": "Number", + "unit": "Second", + "label": "Overheat duration", + "description": "Object cannot shoot while overheat duration is active.", + "group": "Overheat", + "advanced": true, + "name": "OverheatDuration" + }, + { + "value": "0.1", + "type": "Number", + "label": "Linear cooling rate (per second)", + "group": "Overheat", + "advanced": true, + "name": "LinearCoolingRate" + }, + { + "value": "0.3", + "type": "Number", + "label": "Exponential cooling rate (per second)", + "description": "Happens faster when heat is high and slower when heat is low.", + "group": "Overheat", + "extraInformation": [ + "Linear", + "Exponential" + ], + "choices": [], + "advanced": true, + "name": "ExponentialCoolingRate" + }, + { + "value": "", + "type": "String", + "label": "Layer the bullets are created on", + "description": "Base layer by default.", + "group": "Shooting configuration", + "hidden": true, + "name": "BulletLayer" + }, + { + "value": "0", + "type": "Number", + "label": "", + "hidden": true, + "name": "RandomizedAngle" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "FireCooldown" + }, + { + "propertyName": "HasJustFired" + }, + { + "propertyName": "RotateBullet" + }, + { + "folderName": "Multi-Fire", + "children": [ + { + "propertyName": "FiringArc" + }, + { + "propertyName": "BulletQuantity" + } + ] + }, + { + "folderName": "Firing variance", + "children": [ + { + "propertyName": "AngleVariance" + }, + { + "propertyName": "BulletSpeedVariance" + } + ] + }, + { + "propertyName": "AmmoQuantity" + }, + { + "folderName": "Reload", + "children": [ + { + "propertyName": "ShotsPerReload" + }, + { + "propertyName": "ReloadDuration" + }, + { + "propertyName": "AutomaticReloading" + } + ] + }, + { + "folderName": "Ammo", + "children": [ + { + "propertyName": "MaxAmmo" + }, + { + "propertyName": "StartingAmmo" + }, + { + "propertyName": "UnlimitedAmmo" + } + ] + }, + { + "propertyName": "ShotsBeforeNextReload" + }, + { + "propertyName": "TotalShotsFired" + }, + { + "propertyName": "TotalBulletsCreated" + }, + { + "propertyName": "TotalReloadsCompleted" + }, + { + "propertyName": "ReloadInProgress" + }, + { + "folderName": "Overheat", + "children": [ + { + "propertyName": "HeatIncreasePerShot" + }, + { + "propertyName": "OverheatDuration" + }, + { + "propertyName": "LinearCoolingRate" + }, + { + "propertyName": "ExponentialCoolingRate" + } + ] + }, + { + "propertyName": "HeatLevel" + }, + { + "folderName": "Shooting configuration", + "children": [ + { + "propertyName": "BulletLayer" + } + ] + }, + { + "propertyName": "RandomizedAngle" + } + ] + } + } + ], + "eventsBasedObjects": [] + }, + { + "author": "", + "category": "Camera", + "dimension": "3D", + "extensionNamespace": "", + "fullName": "First person 3D camera", + "gdevelopVersion": ">=5.5.222", + "helpPath": "", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMy4wLjMsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iSWNvbnMiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMzIgMzIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDMyIDMyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9DQoJLnN0MXtmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjI7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1taXRlcmxpbWl0OjEwO30NCjwvc3R5bGU+DQo8cGF0aCBjbGFzcz0ic3QwIiBkPSJNMjcsMTZjMCwwLTQuOSw3LTExLDdTNSwxNiw1LDE2czQuOS03LDExLTdTMjcsMTYsMjcsMTZ6Ii8+DQo8Y2lyY2xlIGNsYXNzPSJzdDAiIGN4PSIxNiIgY3k9IjE2IiByPSIzIi8+DQo8cG9seWxpbmUgY2xhc3M9InN0MCIgcG9pbnRzPSIzLDkgMywzIDksMyAiLz4NCjxwb2x5bGluZSBjbGFzcz0ic3QwIiBwb2ludHM9IjksMjkgMywyOSAzLDIzICIvPg0KPHBvbHlsaW5lIGNsYXNzPSJzdDAiIHBvaW50cz0iMjksMjMgMjksMjkgMjMsMjkgIi8+DQo8cG9seWxpbmUgY2xhc3M9InN0MCIgcG9pbnRzPSIyMywzIDI5LDMgMjksOSAiLz4NCjwvc3ZnPg0K", + "name": "FirstPersonCamera", + "previewIconUrl": "https://asset-resources.gdevelop.io/public-resources/Icons/Line Hero Pack/Master/SVG/Security and Protection/e8248ffd504c314e6a9d9d560c3a0fdad3398a5f125ae6a4c0654d4e68c86376_Security and Protection_security_protection_eye_scan_lock.svg", + "shortDescription": "Move the camera to look though objects eyes.", + "version": "1.0.4", + "description": [ + "Move the camera to look though objects eyes.", + "", + "This extension can be used with the \"Mouse pointer lock\" or \"Gamepad\" extension to build a first person camera.", + "", + "The first person example uses this extension ([open the project online](https://editor.gdevelop.io/?project=example://3d-first-person))." + ], + "origin": { + "identifier": "FirstPersonCamera", + "name": "gdevelop-extension-store" + }, + "tags": [ + "3d", + "camera", + "fps" + ], + "authorIds": [ + "IWykYNRvhCZBN3vEgKEbBPOR3Oc2", + "m8kleQHonagHWsvILDhyJhgVhuF2" + ], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [], + "eventsFunctions": [ + { + "description": "Move the camera to look though the object eyes. The object must look to the right when all its angles are 0 and the top of its head be toward Z+.", + "fullName": "Look through object eyes", + "functionType": "Action", + "group": "Layers and cameras", + "name": "LookFromObjectEyes", + "private": true, + "sentence": "Move the camera of _PARAM2_ to look though _PARAM1_ eyes", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "CentreCamera" + }, + "parameters": [ + "", + "Object", + "", + "Layer", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraZ" + }, + "parameters": [ + "", + "=", + "Object.Z()", + "Layer", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraRotationX" + }, + "parameters": [ + "", + "=", + "- Object.RotationY() + 90", + "Layer", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraRotationY" + }, + "parameters": [ + "", + "=", + "Object.RotationX()", + "Layer", + "" + ] + }, + { + "type": { + "value": "SetCameraAngle" + }, + "parameters": [ + "", + "=", + "Object.Angle() + 90", + "Layer", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Scene3D::Cube3DObject", + "type": "objectList" + }, + { + "description": "Layer", + "name": "Layer", + "type": "layer" + } + ], + "objectGroups": [] + }, + { + "description": "Move the camera to look though the object eyes. The object must look to the right when all its angles are 0 and the top of its head be toward Z+.", + "fullName": "Look through object eyes", + "functionType": "Action", + "group": "Layers and cameras", + "name": "LookFrom3DObjectEyes", + "sentence": "Move the camera of _PARAM3_ to look though _PARAM1_ eyes", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "CentreCamera" + }, + "parameters": [ + "", + "Object", + "", + "Layer", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraZ" + }, + "parameters": [ + "", + "=", + "Object.Object3D::Z()", + "Layer", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraRotationX" + }, + "parameters": [ + "", + "=", + "- Object.Object3D::RotationY() + 90", + "Layer", + "" + ] + }, + { + "type": { + "value": "Scene3D::SetCameraRotationY" + }, + "parameters": [ + "", + "=", + "Object.Object3D::RotationX()", + "Layer", + "" + ] + }, + { + "type": { + "value": "SetCameraAngle" + }, + "parameters": [ + "", + "=", + "Object.Angle() + 90", + "Layer", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "3D Object", + "name": "Object", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + }, + { + "description": "Layer", + "name": "Layer", + "type": "layer" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "folderName": "Layers and cameras", + "children": [ + { + "functionName": "LookFromObjectEyes" + }, + { + "functionName": "LookFrom3DObjectEyes" + } + ] + } + ] + }, + "eventsBasedBehaviors": [], + "eventsBasedObjects": [] + } + ], + "externalLayouts": [] +} diff --git a/examples/3d-flight/assets/Bed Bunk.glb b/examples/3d-flight/assets/Bed Bunk.glb new file mode 100644 index 000000000..862c1d18c Binary files /dev/null and b/examples/3d-flight/assets/Bed Bunk.glb differ diff --git a/examples/3d-flight/assets/Blue.png b/examples/3d-flight/assets/Blue.png new file mode 100644 index 000000000..0bd7aa406 Binary files /dev/null and b/examples/3d-flight/assets/Blue.png differ diff --git a/examples/3d-flight/assets/Book 5.glb b/examples/3d-flight/assets/Book 5.glb new file mode 100644 index 000000000..823da26cd Binary files /dev/null and b/examples/3d-flight/assets/Book 5.glb differ diff --git a/examples/3d-flight/assets/Bookcase Open.glb b/examples/3d-flight/assets/Bookcase Open.glb new file mode 100644 index 000000000..f6a982c22 Binary files /dev/null and b/examples/3d-flight/assets/Bookcase Open.glb differ diff --git a/examples/3d-flight/assets/Bottle Ketchup.glb b/examples/3d-flight/assets/Bottle Ketchup.glb new file mode 100644 index 000000000..d9bec0c17 Binary files /dev/null and b/examples/3d-flight/assets/Bottle Ketchup.glb differ diff --git a/examples/3d-flight/assets/Cabinet Bed Drawer Table.glb b/examples/3d-flight/assets/Cabinet Bed Drawer Table.glb new file mode 100644 index 000000000..5981b2f53 Binary files /dev/null and b/examples/3d-flight/assets/Cabinet Bed Drawer Table.glb differ diff --git a/examples/3d-flight/assets/Ceiling.png b/examples/3d-flight/assets/Ceiling.png new file mode 100644 index 000000000..219e2ca35 Binary files /dev/null and b/examples/3d-flight/assets/Ceiling.png differ diff --git a/examples/3d-flight/assets/Chair Cushion.glb b/examples/3d-flight/assets/Chair Cushion.glb new file mode 100644 index 000000000..be85d3c34 Binary files /dev/null and b/examples/3d-flight/assets/Chair Cushion.glb differ diff --git a/examples/3d-flight/assets/Common Tree 1.glb b/examples/3d-flight/assets/Common Tree 1.glb new file mode 100644 index 000000000..59315370a Binary files /dev/null and b/examples/3d-flight/assets/Common Tree 1.glb differ diff --git a/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Back.png b/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Back.png new file mode 100644 index 000000000..16e34f3da Binary files /dev/null and b/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Back.png differ diff --git a/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Bottom.png b/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Bottom.png new file mode 100644 index 000000000..aa0891ef2 Binary files /dev/null and b/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Bottom.png differ diff --git a/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Front.png b/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Front.png new file mode 100644 index 000000000..ce5ae5d6f Binary files /dev/null and b/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Front.png differ diff --git a/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Left.png b/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Left.png new file mode 100644 index 000000000..497b38fe8 Binary files /dev/null and b/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Left.png differ diff --git a/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Right.png b/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Right.png new file mode 100644 index 000000000..a026e8faf Binary files /dev/null and b/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Right.png differ diff --git a/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Top.png b/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Top.png new file mode 100644 index 000000000..377476a78 Binary files /dev/null and b/examples/3d-flight/assets/Cubemap_Sky_04-512x512_Top.png differ diff --git a/examples/3d-flight/assets/Desk.glb b/examples/3d-flight/assets/Desk.glb new file mode 100644 index 000000000..f5c4e68fc Binary files /dev/null and b/examples/3d-flight/assets/Desk.glb differ diff --git a/examples/3d-flight/assets/Doorway.glb b/examples/3d-flight/assets/Doorway.glb new file mode 100644 index 000000000..7e820162d Binary files /dev/null and b/examples/3d-flight/assets/Doorway.glb differ diff --git a/examples/3d-flight/assets/Floor.png b/examples/3d-flight/assets/Floor.png new file mode 100644 index 000000000..80b1a0351 Binary files /dev/null and b/examples/3d-flight/assets/Floor.png differ diff --git a/examples/3d-flight/assets/Grass.png b/examples/3d-flight/assets/Grass.png new file mode 100644 index 000000000..29a5584a2 Binary files /dev/null and b/examples/3d-flight/assets/Grass.png differ diff --git a/examples/3d-flight/assets/Green.png b/examples/3d-flight/assets/Green.png new file mode 100644 index 000000000..36cb5fb64 Binary files /dev/null and b/examples/3d-flight/assets/Green.png differ diff --git a/examples/3d-flight/assets/Male Casual.glb b/examples/3d-flight/assets/Male Casual.glb new file mode 100644 index 000000000..b47997c24 Binary files /dev/null and b/examples/3d-flight/assets/Male Casual.glb differ diff --git a/examples/3d-flight/assets/Marker.png b/examples/3d-flight/assets/Marker.png new file mode 100644 index 000000000..6119ad3e2 Binary files /dev/null and b/examples/3d-flight/assets/Marker.png differ diff --git a/examples/3d-flight/assets/Particle.png b/examples/3d-flight/assets/Particle.png new file mode 100644 index 000000000..1d55472ff Binary files /dev/null and b/examples/3d-flight/assets/Particle.png differ diff --git a/examples/3d-flight/assets/Pink.png b/examples/3d-flight/assets/Pink.png new file mode 100644 index 000000000..e4b827905 Binary files /dev/null and b/examples/3d-flight/assets/Pink.png differ diff --git a/examples/3d-flight/assets/Purple.png b/examples/3d-flight/assets/Purple.png new file mode 100644 index 000000000..5bb210426 Binary files /dev/null and b/examples/3d-flight/assets/Purple.png differ diff --git a/examples/3d-flight/assets/Red.png b/examples/3d-flight/assets/Red.png new file mode 100644 index 000000000..60d757886 Binary files /dev/null and b/examples/3d-flight/assets/Red.png differ diff --git a/examples/3d-flight/assets/Side Table.glb b/examples/3d-flight/assets/Side Table.glb new file mode 100644 index 000000000..b1550e1bc Binary files /dev/null and b/examples/3d-flight/assets/Side Table.glb differ diff --git a/examples/3d-flight/assets/Spaceship Fernando The Flamingo.glb b/examples/3d-flight/assets/Spaceship Fernando The Flamingo.glb new file mode 100644 index 000000000..dd51a3f13 Binary files /dev/null and b/examples/3d-flight/assets/Spaceship Fernando The Flamingo.glb differ diff --git a/examples/3d-flight/assets/Spiky Ball.glb b/examples/3d-flight/assets/Spiky Ball.glb new file mode 100644 index 000000000..944bbd40e Binary files /dev/null and b/examples/3d-flight/assets/Spiky Ball.glb differ diff --git a/examples/3d-flight/assets/Transparent.png b/examples/3d-flight/assets/Transparent.png new file mode 100644 index 000000000..58aa92249 Binary files /dev/null and b/examples/3d-flight/assets/Transparent.png differ diff --git a/examples/3d-flight/assets/Wall.png b/examples/3d-flight/assets/Wall.png new file mode 100644 index 000000000..3f138246e Binary files /dev/null and b/examples/3d-flight/assets/Wall.png differ diff --git a/examples/3d-flight/assets/White.png b/examples/3d-flight/assets/White.png new file mode 100644 index 000000000..b1502d156 Binary files /dev/null and b/examples/3d-flight/assets/White.png differ diff --git a/examples/3d-flight/assets/Wood.png b/examples/3d-flight/assets/Wood.png new file mode 100644 index 000000000..be9f0394b Binary files /dev/null and b/examples/3d-flight/assets/Wood.png differ diff --git a/examples/3d-flight/assets/Yellow.png b/examples/3d-flight/assets/Yellow.png new file mode 100644 index 000000000..e40b93739 Binary files /dev/null and b/examples/3d-flight/assets/Yellow.png differ