diff --git a/examples/3d-lane-runner/3d-lane-runner.json b/examples/3d-lane-runner/3d-lane-runner.json index 3ca111546..98cbeb684 100644 --- a/examples/3d-lane-runner/3d-lane-runner.json +++ b/examples/3d-lane-runner/3d-lane-runner.json @@ -528,6 +528,14 @@ "identifier": "https://asset-resources.gdevelop.io/staging/public-resources/Menu buttons/928c3ea4db1da835c9f8cc5b7089a47228350209d2ff489e1484c31e5ce41b3d_Yellow Button_Pressed.png", "name": "Yellow Button_Pressed.png" } + }, + { + "file": "assets/TrailDropSide.png", + "kind": "image", + "metadata": "", + "name": "assets/TrailDropSide.png", + "smoothed": true, + "userAdded": false } ], "resourceFolders": [] @@ -933,15 +941,15 @@ ] }, { - "b": 182, + "b": 58, "disableInputWhenNotFocused": true, "mangledName": "Game", "name": "Game", - "r": 182, + "r": 58, "standardSortMethod": true, "stopSoundsOnStartup": false, "title": "", - "v": 182, + "v": 58, "uiSettings": { "grid": true, "gridType": "rectangular", @@ -950,10 +958,11 @@ "gridOffsetX": 0, "gridOffsetY": 0, "gridColor": 10401023, - "gridAlpha": 0.8, + "gridAlpha": 0.25, "snap": true, - "zoomFactor": 0.4950840073748954, - "windowMask": false + "zoomFactor": 0.5117784035210265, + "windowMask": false, + "selectedLayer": "" }, "objectsGroups": [ { @@ -1023,11 +1032,9 @@ "layer": "", "name": "Player", "persistentUuid": "386469df-5174-48d4-bd2b-7c45a143a091", - "rotationX": 90, "width": 0, - "x": 434, - "y": 345, - "z": 160, + "x": 0, + "y": 240, "zOrder": 2, "numberProperties": [], "stringProperties": [], @@ -1042,8 +1049,8 @@ "name": "StartMarker", "persistentUuid": "c8a38113-3d6f-4ca7-bec2-a2df28af857a", "width": 64, - "x": 1376, - "y": 224, + "x": 1024, + "y": 0, "zOrder": 3, "numberProperties": [], "stringProperties": [], @@ -1058,9 +1065,9 @@ "name": "Ground", "persistentUuid": "5ced9dfc-1568-4fcc-aaaf-dec2dfca285b", "width": 1024, - "x": 1376, - "y": 416, - "z": 80, + "x": 1024, + "y": 160, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -1075,9 +1082,9 @@ "name": "Ground", "persistentUuid": "56284b4a-71e8-4b60-a4af-21e78d55302e", "width": 1024, - "x": 1376, - "y": 416, - "z": -80, + "x": 1024, + "y": 320, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -1092,30 +1099,14 @@ "name": "Ground", "persistentUuid": "08d9081e-0557-416d-95f4-877058c91ddb", "width": 1024, - "x": 1376, - "y": 416, - "z": 240, + "x": 1024, + "y": 0, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], "initialVariables": [] }, - { - "angle": 0, - "customSize": true, - "depth": 0, - "height": 64, - "layer": "", - "name": "FallDeath", - "persistentUuid": "c3c5b001-89db-4894-9608-ee3d21165eab", - "width": 320, - "x": 352, - "y": 576, - "zOrder": 7, - "numberProperties": [], - "stringProperties": [], - "initialVariables": [] - }, { "angle": 0, "customSize": true, @@ -1125,9 +1116,9 @@ "name": "Ground", "persistentUuid": "642779f9-45f5-4a44-93c5-72c58c7de433", "width": 1024, - "x": 352, - "y": 416, - "z": 80, + "x": 0, + "y": 160, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -1142,9 +1133,9 @@ "name": "Ground", "persistentUuid": "9ac6dbab-a854-48da-929f-642f569887a2", "width": 1024, - "x": 352, - "y": 416, - "z": -80, + "x": 0, + "y": 320, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -1159,9 +1150,9 @@ "name": "Ground", "persistentUuid": "f58781dc-993a-4a9f-947e-0779cb3018a2", "width": 1024, - "x": 352, - "y": 416, - "z": 240, + "x": 0, + "y": 0, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -1176,8 +1167,8 @@ "name": "StartMarker", "persistentUuid": "be3d413d-e99f-4e57-ba14-1fcf2aa38771", "width": 64, - "x": 352, - "y": 224, + "x": 0, + "y": 0, "zOrder": 3, "numberProperties": [], "stringProperties": [], @@ -1186,14 +1177,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "6ee347e0-30d4-4513-b3d3-c70d65192bc9", "width": 64, - "x": 1664, - "y": 352, - "z": 160, + "x": 1312, + "y": 240, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -1202,15 +1194,14 @@ { "angle": 0, "customSize": true, - "depth": 160, - "height": 96, + "depth": 96, + "height": 160, "layer": "", "name": "GroundElevated", "persistentUuid": "dcf1f51f-659e-44af-997c-5b1597ed431d", "width": 448, - "x": 832, - "y": 320, - "z": 80, + "x": 480, + "y": 160, "zOrder": 8, "numberProperties": [], "stringProperties": [], @@ -1219,14 +1210,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "8f060032-c37a-4092-aa92-cf802eca0b83", "width": 64, - "x": 1408, - "y": 352, - "z": 160, + "x": 1056, + "y": 240, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -1235,14 +1227,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "8afc0352-bf3a-44a5-b347-8a3fdfd9cca2", "width": 64, - "x": 1536, - "y": 352, - "z": 160, + "x": 1184, + "y": 240, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -1251,15 +1244,14 @@ { "angle": 0, "customSize": true, - "depth": 160, - "height": 96, + "depth": 96, + "height": 160, "layer": "", "name": "GroundElevated", "persistentUuid": "bbc4ba56-ae80-44c0-8bf0-fd41e8e5dca5", "width": 768, - "x": 1472, + "x": 1120, "y": 320, - "z": -80, "zOrder": 8, "numberProperties": [], "stringProperties": [], @@ -1268,15 +1260,14 @@ { "angle": 0, "customSize": true, - "depth": 160, - "height": 96, + "depth": 96, + "height": 160, "layer": "", "name": "GroundElevated", "persistentUuid": "54d6e161-ad60-4334-bf40-b58225b191ad", "width": 768, - "x": 1472, - "y": 320, - "z": 240, + "x": 1120, + "y": 0, "zOrder": 8, "numberProperties": [], "stringProperties": [], @@ -1285,13 +1276,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "9fa1cdd4-179f-4353-99de-958ed8bc5c65", "width": 64, - "x": 1920, - "y": 256, + "x": 1568, + "y": 400, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -1300,13 +1293,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "89b1e9c1-9530-497f-9509-1def5f104cdd", "width": 64, - "x": 2176, - "y": 256, + "x": 1824, + "y": 400, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -1315,14 +1310,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "a35cd0ca-f211-4740-b6e7-c362d980054b", "width": 64, - "x": 1920, - "y": 256, - "z": 320, + "x": 1568, + "y": 80, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -1331,14 +1327,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "ba36f151-93dd-4fb1-bab3-214d6be4d34b", "width": 64, - "x": 2176, - "y": 256, - "z": 320, + "x": 1824, + "y": 80, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -1347,13 +1344,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "d941556c-58df-4f34-8217-2be06911035a", "width": 64, - "x": 2048, - "y": 256, + "x": 1696, + "y": 400, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -1362,65 +1361,69 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "089b8a11-f0cf-4183-a73c-e37887b17032", "width": 64, - "x": 2048, - "y": 256, - "z": 320, + "x": 1696, + "y": 80, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], "initialVariables": [] }, { - "angle": -45, + "angle": 0, "customSize": true, - "depth": 160, - "height": 136, + "depth": 136, + "height": 160, "layer": "", "name": "GroundElevated", "persistentUuid": "1e0a5571-77b9-4e01-90b3-5738ac4a6715", + "rotationY": -45, "width": 136, - "x": 764, - "y": 348, - "z": 80, + "x": 412, + "y": 160, + "z": -68, "zOrder": 8, "numberProperties": [], "stringProperties": [], "initialVariables": [] }, { - "angle": -45, + "angle": 0, "customSize": true, - "depth": 160, - "height": 136, + "depth": 136, + "height": 160, "layer": "", "name": "GroundElevated", "persistentUuid": "1ad043c7-85f6-4e02-bb52-07e49faf7749", + "rotationY": -45, "width": 136, - "x": 1404, - "y": 348, - "z": -80, + "x": 1052, + "y": 320, + "z": -68, "zOrder": 8, "numberProperties": [], "stringProperties": [], "initialVariables": [] }, { - "angle": -45, + "angle": 0, "customSize": true, - "depth": 160, - "height": 136, + "depth": 136, + "height": 160, "layer": "", "name": "GroundElevated", "persistentUuid": "d40dc4f6-0f8e-4f03-93ed-d414d912f846", + "rotationY": -45, "width": 136, - "x": 1404, - "y": 348, - "z": 240, + "x": 1052, + "y": 0, + "z": -68, "zOrder": 8, "numberProperties": [], "stringProperties": [], @@ -1441,21 +1444,6 @@ "stringProperties": [], "initialVariables": [] }, - { - "angle": 0, - "customSize": false, - "height": 0, - "layer": "UI", - "name": "TutorialText", - "persistentUuid": "5b278fb7-e28f-4668-8575-d5794c7a8550", - "width": 0, - "x": 8, - "y": 1218, - "zOrder": 10, - "numberProperties": [], - "stringProperties": [], - "initialVariables": [] - }, { "angle": 0, "customSize": false, @@ -1470,38 +1458,6 @@ "numberProperties": [], "stringProperties": [], "initialVariables": [] - }, - { - "angle": 0, - "customSize": false, - "height": 0, - "keepRatio": true, - "layer": "UI", - "name": "ScoreLabel", - "persistentUuid": "4c53d15b-82e5-4684-a11d-24b82030dbc8", - "width": 0, - "x": 8, - "y": 0, - "zOrder": 12, - "numberProperties": [], - "stringProperties": [], - "initialVariables": [] - }, - { - "angle": 0, - "customSize": false, - "height": 0, - "keepRatio": true, - "layer": "UI", - "name": "HighScoreLabel", - "persistentUuid": "98faaccd-e19c-4615-8952-c2f49c005f51", - "width": 0, - "x": 8, - "y": 57, - "zOrder": 13, - "numberProperties": [], - "stringProperties": [], - "initialVariables": [] } ], "objects": [ @@ -1522,32 +1478,81 @@ "TargetedLane": 0 }, { - "name": "PlatformerObject", - "type": "PlatformBehavior::PlatformerObjectBehavior", - "ignoreDefaultControls": true, - "acceleration": 2000, - "gravity": 1000, - "jumpSpeed": 750, + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "object3D": "Object3D", + "bodyType": "Dynamic", + "bullet": false, + "fixedRotation": false, + "shape": "Capsule", + "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 + }, + { + "name": "PhysicsCharacter3D", + "type": "Physics3D::PhysicsCharacter3D", + "physics3D": "Physics3D", + "jumpHeight": 150, "jumpSustainTime": 0, - "maxFallingSpeed": 300, - "maxSpeed": 500, - "canGoDownFromJumpthru": true, - "canGrabPlatforms": false, - "canGrabWithoutMoving": true, - "deceleration": 1500, - "ladderClimbingSpeed": 150, + "gravity": 1000, + "fallingSpeedMax": 300, + "forwardAcceleration": 2000, + "forwardDeceleration": 1500, + "forwardSpeedMax": 500, + "sidewaysAcceleration": 800, + "sidewaysDeceleration": 800, + "sidewaysSpeedMax": 400, "slopeMaxAngle": 60, - "useLegacyTrajectory": false, - "xGrabTolerance": 10, - "yGrabOffset": 0 + "stairHeightMax": 20, + "shouldBindObjectAndForwardAngle": true, + "canBePushed": true }, { - "name": "SmoothCameraZ", - "type": "LanePlatformer::SmoothCameraZ", + "name": "ThirdPersonCamera", + "type": "ThirdPersonCamera::ThirdPersonCamera", + "Object3D": "Object3D", + "RotationHalfwayDuration": 0.125, + "ElevationHalfwayDuration": 0, + "TranslationZHalfwayDuration": 0, + "Distance": 440, "OffsetX": 0, - "OffsetY": -100, - "ElevationAngle": 25, - "Distance": 440 + "OffsetY": 0, + "OffsetZ": 60, + "RotationAngleOffset": 0, + "ElevationAngleOffset": 25, + "FollowFreeAreaZMax": 900, + "FollowFreeAreaZMin": 900, + "RotationLogSpeed": 2.0247e-320, + "ElevationLogSpeed": 2.0247e-320, + "TranslationZLogSpeed": 2.0247e-320, + "IsCalledManually": false, + "CameraZ": 0, + "HasJustBeenCreated": true, + "IsRotatingWithObject": true, + "IsElevatingWithObject": false, + "RotationMode": "Z", + "TargetedRotationAngle": 0, + "TargetedElevationAngle": 0, + "ForwardX": 0, + "ForwardY": 0, + "ForwardZ": 0 }, { "name": "Tween", @@ -1564,7 +1569,7 @@ "keepAspectRatio": true, "materialType": "StandardWithoutMetalness", "modelResourceName": "Femal Casual 2.glb", - "originLocation": "ObjectCenter", + "originLocation": "ModelOrigin", "rotationX": 90, "rotationY": 0, "rotationZ": 90, @@ -1640,48 +1645,6 @@ } ] }, - { - "adaptCollisionMaskAutomatically": false, - "assetStoreId": "", - "name": "FallDeath", - "type": "Sprite", - "updateIfNotVisible": false, - "variables": [], - "effects": [], - "behaviors": [], - "animations": [ - { - "name": "NewSprite", - "useMultipleDirections": false, - "directions": [ - { - "looping": false, - "metadata": "{\"pskl\":{}}", - "timeBetweenFrames": 0.08, - "sprites": [ - { - "hasCustomCollisionMask": false, - "image": "NewSprite", - "points": [], - "originPoint": { - "name": "origine", - "x": 0, - "y": 0 - }, - "centerPoint": { - "automatic": true, - "name": "centre", - "x": 0, - "y": 0 - }, - "customCollisionMask": [] - } - ] - } - ] - } - ] - }, { "assetStoreId": "", "name": "Ground", @@ -1690,11 +1653,32 @@ "effects": [], "behaviors": [ { - "name": "Platform", - "type": "PlatformBehavior::PlatformBehavior", - "canBeGrabbed": true, - "platformType": "NormalPlatform", - "yGrabOffset": 0 + "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": { @@ -1702,26 +1686,26 @@ "height": 100, "depth": 100, "enableTextureTransparency": true, - "facesOrientation": "Y", - "frontFaceResourceName": "", + "facesOrientation": "Z", + "frontFaceResourceName": "Trail3.png", "backFaceResourceName": "", "backFaceUpThroughWhichAxisRotation": "X", "leftFaceResourceName": "TrailDrop.png", "rightFaceResourceName": "", - "topFaceResourceName": "Trail3.png", - "bottomFaceResourceName": "", - "frontFaceVisible": false, + "topFaceResourceName": "assets/TrailDropSide.png", + "bottomFaceResourceName": "assets/TrailDropSide.png", + "frontFaceVisible": true, "backFaceVisible": false, "leftFaceVisible": true, "rightFaceVisible": false, "topFaceVisible": true, - "bottomFaceVisible": false, - "frontFaceResourceRepeat": false, + "bottomFaceVisible": true, + "frontFaceResourceRepeat": true, "backFaceResourceRepeat": false, "leftFaceResourceRepeat": false, "rightFaceResourceRepeat": false, "topFaceResourceRepeat": true, - "bottomFaceResourceRepeat": false, + "bottomFaceResourceRepeat": true, "materialType": "StandardWithoutMetalness", "isCastingShadow": true, "isReceivingShadow": true @@ -1735,11 +1719,32 @@ "effects": [], "behaviors": [ { - "name": "Platform", - "type": "PlatformBehavior::PlatformBehavior", - "canBeGrabbed": true, - "platformType": "NormalPlatform", - "yGrabOffset": 0 + "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": { @@ -1747,25 +1752,25 @@ "height": 100, "depth": 100, "enableTextureTransparency": true, - "facesOrientation": "Y", - "frontFaceResourceName": "TrailWall.png", - "backFaceResourceName": "TrailWall.png", + "facesOrientation": "Z", + "frontFaceResourceName": "Trail3.png", + "backFaceResourceName": "", "backFaceUpThroughWhichAxisRotation": "X", "leftFaceResourceName": "TrailDrop.png", "rightFaceResourceName": "", - "topFaceResourceName": "Trail3.png", - "bottomFaceResourceName": "", + "topFaceResourceName": "TrailWall.png", + "bottomFaceResourceName": "TrailWall.png", "frontFaceVisible": true, - "backFaceVisible": true, + "backFaceVisible": false, "leftFaceVisible": true, "rightFaceVisible": false, "topFaceVisible": true, - "bottomFaceVisible": false, - "frontFaceResourceRepeat": false, + "bottomFaceVisible": true, + "frontFaceResourceRepeat": true, "backFaceResourceRepeat": false, "leftFaceResourceRepeat": false, "rightFaceResourceRepeat": false, - "topFaceResourceRepeat": true, + "topFaceResourceRepeat": false, "bottomFaceResourceRepeat": false, "materialType": "StandardWithoutMetalness", "isCastingShadow": true, @@ -1778,16 +1783,11 @@ "type": "Scene3D::Model3DObject", "variables": [], "effects": [], - "behaviors": [ - { - "name": "LaneObject", - "type": "LanePlatformer::LaneObject" - } - ], + "behaviors": [], "content": { "centerLocation": "ObjectCenter", "crossfadeDuration": 0, - "depth": 99, + "depth": 98.99998035017916, "height": 99, "isCastingShadow": true, "isReceivingShadow": true, @@ -1795,9 +1795,9 @@ "materialType": "KeepOriginal", "modelResourceName": "Spike Group.glb", "originLocation": "ObjectCenter", - "rotationX": 0, + "rotationX": 90, "rotationY": 0, - "rotationZ": 0, + "rotationZ": 90, "width": 99, "animations": [] } @@ -1812,27 +1812,23 @@ { "name": "Collectible", "type": "Collectible::Collectible" - }, - { - "name": "LaneObject", - "type": "LanePlatformer::LaneObject" } ], "content": { "centerLocation": "ModelOrigin", "crossfadeDuration": 0, - "depth": 18.752, - "height": 62.66935348510742, + "depth": 62.66935348510742, + "height": 59.60209369659424, "isCastingShadow": true, "isReceivingShadow": false, "keepAspectRatio": true, "materialType": "KeepOriginal", "modelResourceName": "Coin.glb", "originLocation": "ModelOrigin", - "rotationX": 0, + "rotationX": 90, "rotationY": 0, - "rotationZ": 0, - "width": 59.60209369659424, + "rotationZ": 90, + "width": 18.75197410583499, "animations": [] } }, @@ -1991,7 +1987,7 @@ "Blending": "Normal", "StartSizeMax": 20, "Gravity": -500, - "GravityTop": "Y-" + "GravityTop": "Z+" }, "childrenContent": { "Particle": { @@ -2085,9 +2081,6 @@ "folderName": "Invisible Borders", "quickCustomizationVisibility": "hidden", "children": [ - { - "objectName": "FallDeath" - }, { "objectName": "StartMarker" } @@ -2121,6 +2114,18 @@ } ], "actions": [ + { + "type": { + "value": "BuiltinExternalLayouts::CreateObjectsFromExternalLayout" + }, + "parameters": [ + "", + "\"UI\"", + "0", + "0", + "" + ] + }, { "type": { "value": "SetStringVariable" @@ -2171,19 +2176,6 @@ "=", "1.3" ] - }, - { - "type": { - "value": "LanePlatformer::LaneCharacter::EnablePlatformOnLane" - }, - "parameters": [ - "Player", - "LaneCharacter", - "Platform", - "Object3D", - "Platform", - "" - ] } ], "events": [ @@ -2339,12 +2331,11 @@ "actions": [ { "type": { - "value": "PlatformBehavior::SimulateControl" + "value": "Physics3D::PhysicsCharacter3D::SimulateForwardKey" }, "parameters": [ "Player", - "PlatformerObject", - "\"Right\"" + "PhysicsCharacter3D" ] } ] @@ -2411,12 +2402,11 @@ "actions": [ { "type": { - "value": "PlatformBehavior::SimulateControl" + "value": "Physics3D::PhysicsCharacter3D::SimulateJumpKey" }, "parameters": [ "Player", - "PlatformerObject", - "\"Jump\"" + "PhysicsCharacter3D" ] } ] @@ -2426,206 +2416,180 @@ "conditions": [ { "type": { - "inverted": true, - "value": "CollisionNP" + "value": "BuiltinCommonInstructions::Or" }, - "parameters": [ - "Player", - "GroundElevated", - "", - "", - "yes" - ] - } - ], - "actions": [], - "events": [ - { - "type": "BuiltinCommonInstructions::Standard", - "conditions": [ + "parameters": [], + "subInstructions": [ { "type": { - "value": "BuiltinCommonInstructions::Or" + "value": "KeyPressed" + }, + "parameters": [ + "", + "d" + ] + }, + { + "type": { + "value": "KeyPressed" + }, + "parameters": [ + "", + "Right" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::And" }, "parameters": [], "subInstructions": [ { "type": { - "value": "KeyPressed" + "value": "SwipeGesture::SwipeDirection_4way" }, "parameters": [ "", - "d" + "\"Right\"", + "" ] }, { "type": { - "value": "KeyPressed" + "value": "SwipeGesture::Distance" }, "parameters": [ "", - "Right" + ">", + "100", + "" ] }, { "type": { - "value": "BuiltinCommonInstructions::And" + "value": "SwipeGesture::HasSwipeJustEnded" }, - "parameters": [], - "subInstructions": [ - { - "type": { - "value": "SwipeGesture::SwipeDirection_4way" - }, - "parameters": [ - "", - "\"Right\"", - "" - ] - }, - { - "type": { - "value": "SwipeGesture::Distance" - }, - "parameters": [ - "", - ">", - "100", - "" - ] - }, - { - "type": { - "value": "SwipeGesture::HasSwipeJustEnded" - }, - "parameters": [ - "", - "" - ] - } + "parameters": [ + "", + "" ] } ] } - ], - "actions": [ + ] + }, + { + "type": { + "inverted": true, + "value": "Raycaster3D::RaycastBetweenPosition" + }, + "parameters": [ + "", + "Platform", + "Player.X()", + "Player.Y()", + "Player.Z() + 2", + "Player.X()", + "Player.Y() + 160", + "Player.Z() + 2", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "LanePlatformer::LaneCharacter::MoveRight" + }, + "parameters": [ + "Player", + "LaneCharacter", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "KeyPressed" + }, + "parameters": [ + "", + "a" + ] + }, { "type": { - "value": "LanePlatformer::LaneCharacter::MoveRight" + "value": "KeyPressed" }, "parameters": [ - "Player", - "LaneCharacter", - "" + "", + "Left" ] - } - ] - }, - { - "type": "BuiltinCommonInstructions::Standard", - "conditions": [ + }, { "type": { - "value": "BuiltinCommonInstructions::Or" + "value": "BuiltinCommonInstructions::And" }, "parameters": [], "subInstructions": [ { "type": { - "value": "KeyPressed" + "value": "SwipeGesture::SwipeDirection_4way" }, "parameters": [ "", - "a" + "\"Left\"", + "" ] }, { "type": { - "value": "KeyPressed" + "value": "SwipeGesture::Distance" }, "parameters": [ "", - "Left" + ">", + "100", + "" ] }, { "type": { - "value": "BuiltinCommonInstructions::And" + "value": "SwipeGesture::HasSwipeJustEnded" }, - "parameters": [], - "subInstructions": [ - { - "type": { - "value": "SwipeGesture::SwipeDirection_4way" - }, - "parameters": [ - "", - "\"Left\"", - "" - ] - }, - { - "type": { - "value": "SwipeGesture::Distance" - }, - "parameters": [ - "", - ">", - "100", - "" - ] - }, - { - "type": { - "value": "SwipeGesture::HasSwipeJustEnded" - }, - "parameters": [ - "", - "" - ] - } + "parameters": [ + "", + "" ] } ] } - ], - "actions": [ - { - "type": { - "value": "LanePlatformer::LaneCharacter::MoveLeft" - }, - "parameters": [ - "Player", - "LaneCharacter", - "" - ] - } ] - } - ] - }, - { - "type": "BuiltinCommonInstructions::Comment", - "color": { - "b": 109, - "g": 230, - "r": 255, - "textB": 0, - "textG": 0, - "textR": 0 - }, - "comment": "Lane change end\nChecking which objects are valid after the player changes lanes." - }, - { - "type": "BuiltinCommonInstructions::Standard", - "conditions": [ + }, { "type": { - "value": "LanePlatformer::LaneCharacter::HasChangedOfLane" + "inverted": true, + "value": "Raycaster3D::RaycastBetweenPosition" }, "parameters": [ - "Player", - "LaneCharacter", + "", + "Platform", + "Player.X()", + "Player.Y()", + "Player.Z() + 2", + "Player.X()", + "Player.Y() - 160", + "Player.Z() + 2", "" ] } @@ -2633,14 +2597,11 @@ "actions": [ { "type": { - "value": "LanePlatformer::LaneCharacter::EnablePlatformOnLane" + "value": "LanePlatformer::LaneCharacter::MoveLeft" }, "parameters": [ "Player", "LaneCharacter", - "Platform", - "Object3D", - "Platform", "" ] } @@ -2675,24 +2636,13 @@ "conditions": [ { "type": { - "value": "LanePlatformer::LaneObject::IsObjectOnSameLane" - }, - "parameters": [ - "Coin", - "LaneObject", - "Player", - "LaneCharacter", - "" - ] - }, - { - "type": { - "value": "CollisionNP" + "value": "Collision3D::AreWithinDistance" }, "parameters": [ + "", "Coin", "Player", - "", + "75", "", "" ] @@ -2803,12 +2753,13 @@ "conditions": [ { "type": { - "value": "PosY" + "value": "Scene3D::Base3DBehavior::Z" }, "parameters": [ "Player", - ">", - "FallDeath.Y()" + "Object3D", + "<", + "-50" ] } ], @@ -2825,41 +2776,18 @@ } ] }, - { - "type": "BuiltinCommonInstructions::Comment", - "color": { - "b": 109, - "g": 230, - "r": 255, - "textB": 0, - "textG": 0, - "textR": 0 - }, - "comment": "Collision checks if objects are in the proper lane." - }, { "type": "BuiltinCommonInstructions::Standard", "conditions": [ { "type": { - "value": "LanePlatformer::LaneObject::IsObjectOnSameLane" - }, - "parameters": [ - "SpikeGroup", - "LaneObject", - "Player", - "LaneCharacter", - "" - ] - }, - { - "type": { - "value": "CollisionNP" + "value": "Collision3D::AreWithinDistance" }, "parameters": [ + "", "SpikeGroup", "Player", - "", + "75", "", "" ] @@ -3136,27 +3064,6 @@ "StartMarker.Y()" ] } - ], - "events": [ - { - "type": "BuiltinCommonInstructions::Standard", - "conditions": [], - "actions": [ - { - "type": { - "value": "LanePlatformer::LaneCharacter::EnablePlatformOnLane" - }, - "parameters": [ - "Player", - "LaneCharacter", - "Platform", - "Object3D", - "Platform", - "" - ] - } - ] - } ] } ] @@ -3242,7 +3149,7 @@ "stringParameters": { "groundColor": "192;192;192", "skyColor": "253;255;219", - "top": "Y-" + "top": "Z+" }, "booleanParameters": {} }, @@ -3264,14 +3171,14 @@ "doubleParameters": { "distanceFromCamera": 700, "elevation": 45, - "frustumSize": 2800, + "frustumSize": 3500, "intensity": 0.5, "minimumShadowBias": 0, "rotation": 235 }, "stringParameters": { "color": "254;255;235", - "top": "Y-" + "top": "Z+" }, "booleanParameters": { "isCastingShadow": true @@ -3318,10 +3225,6 @@ "name": "LaneCharacter", "type": "LanePlatformer::LaneCharacter" }, - { - "name": "LaneObject", - "type": "LanePlatformer::LaneObject" - }, { "name": "Object3D", "type": "Scene3D::Base3DBehavior" @@ -3331,12 +3234,16 @@ "type": "OpacityCapability::OpacityBehavior" }, { - "name": "Platform", - "type": "PlatformBehavior::PlatformBehavior" + "name": "Physics3D", + "type": "Physics3D::Physics3DBehavior", + "gravityX": 0, + "gravityY": 0, + "gravityZ": -9.8, + "worldScale": 100 }, { - "name": "PlatformerObject", - "type": "PlatformBehavior::PlatformerObjectBehavior" + "name": "PhysicsCharacter3D", + "type": "Physics3D::PhysicsCharacter3D" }, { "name": "Resizable", @@ -3346,14 +3253,14 @@ "name": "Scale", "type": "ScalableCapability::ScalableBehavior" }, - { - "name": "SmoothCameraZ", - "type": "LanePlatformer::SmoothCameraZ" - }, { "name": "Text", "type": "TextContainerCapability::TextContainerBehavior" }, + { + "name": "ThirdPersonCamera", + "type": "ThirdPersonCamera::ThirdPersonCamera" + }, { "name": "Tween", "type": "Tween::TweenBehavior" @@ -22742,7 +22649,7 @@ "Object", "Behavior", "=", - "Object.Behavior::LaneOf(Object.Object3D::CenterZ())" + "Object.Behavior::LaneOf(Object.CenterY())" ] }, { @@ -22837,17 +22744,16 @@ "actions": [ { "type": { - "value": "Tween::AddObjectPositionZTween2" + "value": "Tween::TweenBehavior::AddObjectPositionYTween2" }, "parameters": [ "Object", "Tween", - "Object3D", "\"Move\"", - "TargetedLane * LaneDepth", + "(TargetedLane + 0.5 ) * LaneDepth", "\"linear\"", "LaneChangeDuration", - "" + "LaneChangeDuration" ] } ] @@ -23188,7 +23094,7 @@ "Behavior", "=", "Lane", - "OtherObject.Object3D::CenterZ()", + "OtherObject.CenterY()", "Object3D" ] } @@ -23248,7 +23154,7 @@ "value": "SetReturnNumber" }, "parameters": [ - "round(CenterZ / LaneDepth)" + "round(-0.5 + CenterY / LaneDepth)" ] } ] @@ -23271,8 +23177,8 @@ "type": "behavior" }, { - "description": "Center Z", - "name": "CenterZ", + "description": "Center Y", + "name": "CenterY", "type": "expression" } ], @@ -23638,69 +23544,95 @@ } ], "sharedPropertyDescriptors": [] - }, + } + ], + "eventsBasedObjects": [] + }, + { + "author": "", + "category": "", + "extensionNamespace": "", + "fullName": "", + "gdevelopVersion": "", + "helpPath": "", + "iconUrl": "", + "name": "Collectible", + "previewIconUrl": "", + "shortDescription": "", + "version": "", + "description": "", + "tags": [], + "authorIds": [], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [ { - "description": "Smoothly follow an object on Z axis.", - "fullName": "Smooth camera on Z", - "name": "SmoothCameraZ", - "objectType": "Scene3D::Model3DObject", - "eventsFunctions": [ + "folded": true, + "name": "RisingPitch", + "type": "number", + "value": 0.8 + } + ], + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onScenePreEvents", + "sentence": "", + "events": [ { - "fullName": "", - "functionType": "Action", - "name": "onCreated", - "sentence": "", - "events": [ + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ { - "type": "BuiltinCommonInstructions::Comment", - "color": { - "b": 109, - "g": 230, - "r": 255, - "textB": 0, - "textG": 0, - "textR": 0 + "type": { + "value": "CompareTimer" }, - "comment": "ln((1 - speed)) = ln(1 / 2) / halfwatTime" - }, - { - "type": "BuiltinCommonInstructions::Standard", - "conditions": [], - "actions": [ - { - "type": { - "value": "LanePlatformer::SmoothCameraZ::SetPropertyTranslationZLogSpeed" - }, - "parameters": [ - "Object", - "Behavior", - "=", - "log(0.5) / TranslationZHalfwayDuration" - ] - } + "parameters": [ + "", + "\"RisingPitch\"", + ">", + "1" ] } ], - "parameters": [ + "actions": [ { - "description": "Object", - "name": "Object", - "supplementaryInformation": "Scene3D::Model3DObject", - "type": "object" + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "RisingPitch", + "=", + "0.8" + ] }, { - "description": "Behavior", - "name": "Behavior", - "supplementaryInformation": "LanePlatformer::SmoothCameraZ", - "type": "behavior" + "type": { + "value": "RemoveTimer" + }, + "parameters": [ + "", + "\"RisingPitch\"" + ] } - ], - "objectGroups": [] - }, + ] + } + ], + "parameters": [], + "objectGroups": [] + } + ], + "eventsBasedBehaviors": [ + { + "description": "Rotate continuously and make a sound when deleted.", + "fullName": "Collectible", + "name": "Collectible", + "objectType": "Scene3D::Model3DObject", + "eventsFunctions": [ { "fullName": "", "functionType": "Action", - "name": "doStepPreEvents", + "name": "onDestroy", "sentence": "", "events": [ { @@ -23713,107 +23645,41 @@ "textG": 0, "textR": 0 }, - "comment": "Adjusting the default camera position." + "comment": "Reseting the rising pitch variable after being adjusted in the coin collision event." }, { "type": "BuiltinCommonInstructions::Standard", - "conditions": [ - { - "type": { - "value": "BuiltinCommonInstructions::Once" - }, - "parameters": [] - } - ], + "conditions": [], "actions": [ { "type": { - "value": "SetCameraCenterY" - }, - "parameters": [ - "", - "=", - "Object.CenterY() + OffsetY + YFromAngleAndDistance(ElevationAngle + 180, Distance)", - "", - "" - ] - }, - { - "type": { - "value": "Scene3D::SetCameraZ" - }, - "parameters": [ - "", - "=", - "Object.Object3D::CenterZ()", - "", - "" - ] - }, - { - "type": { - "value": "Scene3D::SetCameraRotationY" + "value": "PlaySound" }, "parameters": [ "", - "=", - "-90", + "CoinPickUp", "", - "" + "50", + "RisingPitch" ] }, { "type": { - "value": "Scene3D::SetCameraRotationX" - }, - "parameters": [ - "", - "=", - "-ElevationAngle", - "", - "" - ] - } - ] - }, - { - "type": "BuiltinCommonInstructions::Comment", - "color": { - "b": 109, - "g": 230, - "r": 255, - "textB": 0, - "textG": 0, - "textR": 0 - }, - "comment": "Constant camera movement to follow the player." - }, - { - "type": "BuiltinCommonInstructions::Standard", - "conditions": [], - "actions": [ - { - "type": { - "value": "Scene3D::SetCameraZ" + "value": "SetNumberVariable" }, "parameters": [ - "", - "=", - "Object.Object3D::CenterZ() + (Scene3D::CameraZ() - Object.Object3D::CenterZ()) * exp(TimeDelta() * TranslationZLogSpeed)", - "", - "" + "RisingPitch", + "*", + "1.03" ] }, { "type": { - "value": "SetCameraCenterX" + "value": "ResetTimer" }, "parameters": [ "", - "=", - "Object.CenterX() + OffsetX + XFromAngleAndDistance(ElevationAngle + 180, Distance)", - "", - "" + "\"RisingPitch\"" ] } ] @@ -23829,74 +23695,17 @@ { "description": "Behavior", "name": "Behavior", - "supplementaryInformation": "LanePlatformer::SmoothCameraZ", + "supplementaryInformation": "Collectible::Collectible", "type": "behavior" } ], "objectGroups": [] - } - ], - "propertyDescriptors": [ - { - "value": "0", - "type": "Number", - "unit": "Pixel", - "label": "X offset", - "advanced": true, - "name": "OffsetX" - }, - { - "value": "-100", - "type": "Number", - "unit": "Pixel", - "label": "Y offset", - "advanced": true, - "name": "OffsetY" - }, - { - "value": "400", - "type": "Number", - "unit": "Pixel", - "label": "Camera distance", - "name": "Distance" - }, - { - "value": "20", - "type": "Number", - "unit": "DegreeAngle", - "label": "Camera elevation angle", - "name": "ElevationAngle" - }, - { - "value": "0.125", - "type": "Number", - "unit": "Second", - "label": "Halfway time on Z axis", - "group": "Catch-up speed", - "advanced": true, - "name": "TranslationZHalfwayDuration" }, { - "value": "", - "type": "Number", - "label": "", - "hidden": true, - "name": "TranslationZLogSpeed" - } - ], - "sharedPropertyDescriptors": [] - }, - { - "description": "Allow to check the object lane.", - "fullName": "Lane object", - "name": "LaneObject", - "objectType": "Scene3D::Model3DObject", - "eventsFunctions": [ - { - "fullName": "Is on same lane", - "functionType": "Condition", - "name": "IsObjectOnSameLane", - "sentence": "_PARAM0_ on the same lane as _PARAM2_", + "fullName": "", + "functionType": "Action", + "name": "doStepPreEvents", + "sentence": "", "events": [ { "type": "BuiltinCommonInstructions::Comment", @@ -23908,31 +23717,20 @@ "textG": 0, "textR": 0 }, - "comment": "This behavior only allow to pick the objects where the one from LaneCharacter only pick the characters." + "comment": "Rotating the coins in game." }, { "type": "BuiltinCommonInstructions::Standard", - "conditions": [ - { - "type": { - "value": "LanePlatformer::LaneCharacter::IsObjectOnSameLane" - }, - "parameters": [ - "Character", - "LaneCharacter", - "Object", - "Object3D", - "" - ] - } - ], + "conditions": [], "actions": [ { "type": { - "value": "SetReturnBoolean" + "value": "Rotate" }, "parameters": [ - "True" + "Object", + "RotationSpeed", + "+" ] } ] @@ -23948,26 +23746,22 @@ { "description": "Behavior", "name": "Behavior", - "supplementaryInformation": "LanePlatformer::LaneObject", - "type": "behavior" - }, - { - "description": "Character", - "name": "Character", - "supplementaryInformation": "Scene3D::Model3DObject", - "type": "objectList" - }, - { - "description": "Lane platformer character", - "name": "LaneCharacter", - "supplementaryInformation": "LanePlatformer::LaneCharacter", + "supplementaryInformation": "Collectible::Collectible", "type": "behavior" } ], "objectGroups": [] } ], - "propertyDescriptors": [], + "propertyDescriptors": [ + { + "value": "60", + "type": "Number", + "unit": "AngularSpeed", + "label": "Rotation speed", + "name": "RotationSpeed" + } + ], "sharedPropertyDescriptors": [] } ], @@ -23975,229 +23769,9 @@ }, { "author": "", - "category": "", + "category": "User interface", "extensionNamespace": "", - "fullName": "", - "gdevelopVersion": "", - "helpPath": "", - "iconUrl": "", - "name": "Collectible", - "previewIconUrl": "", - "shortDescription": "", - "version": "", - "description": "", - "tags": [], - "authorIds": [], - "dependencies": [], - "globalVariables": [], - "sceneVariables": [ - { - "folded": true, - "name": "RisingPitch", - "type": "number", - "value": 0.8 - } - ], - "eventsFunctions": [ - { - "fullName": "", - "functionType": "Action", - "name": "onScenePreEvents", - "sentence": "", - "events": [ - { - "type": "BuiltinCommonInstructions::Standard", - "conditions": [ - { - "type": { - "value": "CompareTimer" - }, - "parameters": [ - "", - "\"RisingPitch\"", - ">", - "1" - ] - } - ], - "actions": [ - { - "type": { - "value": "SetNumberVariable" - }, - "parameters": [ - "RisingPitch", - "=", - "0.8" - ] - }, - { - "type": { - "value": "RemoveTimer" - }, - "parameters": [ - "", - "\"RisingPitch\"" - ] - } - ] - } - ], - "parameters": [], - "objectGroups": [] - } - ], - "eventsBasedBehaviors": [ - { - "description": "Rotate continuously and make a sound when deleted.", - "fullName": "Collectible", - "name": "Collectible", - "objectType": "Scene3D::Model3DObject", - "eventsFunctions": [ - { - "fullName": "", - "functionType": "Action", - "name": "onDestroy", - "sentence": "", - "events": [ - { - "type": "BuiltinCommonInstructions::Comment", - "color": { - "b": 109, - "g": 230, - "r": 255, - "textB": 0, - "textG": 0, - "textR": 0 - }, - "comment": "Reseting the rising pitch variable after being adjusted in the coin collision event." - }, - { - "type": "BuiltinCommonInstructions::Standard", - "conditions": [], - "actions": [ - { - "type": { - "value": "PlaySound" - }, - "parameters": [ - "", - "CoinPickUp", - "", - "50", - "RisingPitch" - ] - }, - { - "type": { - "value": "SetNumberVariable" - }, - "parameters": [ - "RisingPitch", - "*", - "1.03" - ] - }, - { - "type": { - "value": "ResetTimer" - }, - "parameters": [ - "", - "\"RisingPitch\"" - ] - } - ] - } - ], - "parameters": [ - { - "description": "Object", - "name": "Object", - "supplementaryInformation": "Scene3D::Model3DObject", - "type": "object" - }, - { - "description": "Behavior", - "name": "Behavior", - "supplementaryInformation": "Collectible::Collectible", - "type": "behavior" - } - ], - "objectGroups": [] - }, - { - "fullName": "", - "functionType": "Action", - "name": "doStepPreEvents", - "sentence": "", - "events": [ - { - "type": "BuiltinCommonInstructions::Comment", - "color": { - "b": 109, - "g": 230, - "r": 255, - "textB": 0, - "textG": 0, - "textR": 0 - }, - "comment": "Rotating the coins in game." - }, - { - "type": "BuiltinCommonInstructions::Standard", - "conditions": [], - "actions": [ - { - "type": { - "value": "Scene3D::Base3DBehavior::SetRotationY" - }, - "parameters": [ - "Object", - "Object3D", - "+", - "RotationSpeed * TimeDelta()" - ] - } - ] - } - ], - "parameters": [ - { - "description": "Object", - "name": "Object", - "supplementaryInformation": "Scene3D::Model3DObject", - "type": "object" - }, - { - "description": "Behavior", - "name": "Behavior", - "supplementaryInformation": "Collectible::Collectible", - "type": "behavior" - } - ], - "objectGroups": [] - } - ], - "propertyDescriptors": [ - { - "value": "60", - "type": "Number", - "unit": "AngularSpeed", - "label": "Rotation speed", - "name": "RotationSpeed" - } - ], - "sharedPropertyDescriptors": [] - } - ], - "eventsBasedObjects": [] - }, - { - "author": "", - "category": "User interface", - "extensionNamespace": "", - "fullName": "Leaderboard dialog", + "fullName": "Leaderboard dialog", "gdevelopVersion": "", "helpPath": "", "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0ibWRpLXRyb3BoeSIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxwYXRoIGQ9Ik0xOCAyQzE3LjEgMiAxNiAzIDE2IDRIOEM4IDMgNi45IDIgNiAySDJWMTFDMiAxMiAzIDEzIDQgMTNINi4yQzYuNiAxNSA3LjkgMTYuNyAxMSAxN1YxOS4wOEM4IDE5LjU0IDggMjIgOCAyMkgxNkMxNiAyMiAxNiAxOS41NCAxMyAxOS4wOFYxN0MxNi4xIDE2LjcgMTcuNCAxNSAxNy44IDEzSDIwQzIxIDEzIDIyIDEyIDIyIDExVjJIMThNNiAxMUg0VjRINlYxMU0yMCAxMUgxOFY0SDIwVjExWiIgLz48L3N2Zz4=", @@ -26932,24 +26506,9825 @@ "initialVariables": [] } ], - "editionSettings": { - "grid": false, - "gridType": "rectangular", - "gridWidth": 32, - "gridHeight": 32, - "gridOffsetX": 0, - "gridOffsetY": 0, - "gridColor": 10401023, - "gridAlpha": 0.8, - "snap": false, - "zoomFactor": 1.0174418604651163, - "windowMask": false, - "selectedLayer": "" - } + "editionSettings": { + "grid": false, + "gridType": "rectangular", + "gridWidth": 32, + "gridHeight": 32, + "gridOffsetX": 0, + "gridOffsetY": 0, + "gridColor": 10401023, + "gridAlpha": 0.8, + "snap": false, + "zoomFactor": 1.0174418604651163, + "windowMask": false, + "selectedLayer": "" + } + } + ] + } + ] + }, + { + "author": "", + "category": "Camera", + "extensionNamespace": "", + "fullName": "Smooth Camera", + "gdevelopVersion": ">=5.5.222", + "helpPath": "/tutorials/follow-player-with-camera/", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMy4wLjMsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iSWNvbnMiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMzIgMzIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDMyIDMyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9DQoJLnN0MXtmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjI7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS1taXRlcmxpbWl0OjEwO30NCjwvc3R5bGU+DQo8cGF0aCBjbGFzcz0ic3QwIiBkPSJNMjQsMTNoLTZjLTEuMSwwLTItMC45LTItMlY1YzAtMS4xLDAuOS0yLDItMmg2YzEuMSwwLDIsMC45LDIsMnY2QzI2LDEyLjEsMjUuMSwxMywyNCwxM3oiLz4NCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0yNiw4djEwYzAsMS4xLTAuOSwyLTIsMkg4Yy0xLjEsMC0yLTAuOS0yLTJWOGMwLTEuMSwwLjktMiwyLTJoOCIvPg0KPGNpcmNsZSBjbGFzcz0ic3QwIiBjeD0iMjEiIGN5PSI4IiByPSIyIi8+DQo8Y2lyY2xlIGNsYXNzPSJzdDAiIGN4PSIxMSIgY3k9IjE2IiByPSIxIi8+DQo8cmVjdCB4PSI5IiB5PSI5IiBjbGFzcz0ic3QwIiB3aWR0aD0iNCIgaGVpZ2h0PSIzIi8+DQo8cG9seWxpbmUgY2xhc3M9InN0MCIgcG9pbnRzPSIyMSwyOSAyMSwyOSAxMSwyOSAxMSwyOSAiLz4NCjxwb2x5bGluZSBjbGFzcz0ic3QwIiBwb2ludHM9IjE4LDIwIDE4LDI5IDE0LDI5IDE0LDIwICIvPg0KPHJlY3QgeD0iNyIgeT0iMyIgY2xhc3M9InN0MCIgd2lkdGg9IjQiIGhlaWdodD0iMyIvPg0KPC9zdmc+DQo=", + "name": "SmoothCamera", + "previewIconUrl": "https://resources.gdevelop-app.com/assets/Icons/Line Hero Pack/Master/SVG/Computers and Hardware/Computers and Hardware_camcoder_gopro_go_pro_camera.svg", + "shortDescription": "Smoothly scroll to follow an object.", + "version": "0.4.4", + "description": [ + "The camera follows an object according to:", + "- a frame rate independent catch-up speed to make the scrolling from smooth to strong", + "- a maximum speed to do linear following ([open the project online](https://editor.gdevelop.io/?project=example://platformer-with-tilemap)) or slow down the camera when teleporting the object", + "- a follow-free zone to avoid scrolling on small movements", + "- an offset to see further in one direction", + "- an extra delay and catch-up speed to give an impression of speed (useful for dash)", + "- position forecasting and delay to simulate a cameraman response time", + "", + "A platformer dedicated behavior allows to switch of settings when the character is in air or on the floor. This can be used to stabilize the camera when jumping." + ], + "origin": { + "identifier": "SmoothCamera", + "name": "gdevelop-extension-store" + }, + "tags": [ + "camera", + "scrolling", + "follow", + "smooth", + "platformer", + "platform" + ], + "authorIds": [ + "IWykYNRvhCZBN3vEgKEbBPOR3Oc2" + ], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [], + "eventsFunctions": [], + "eventsBasedBehaviors": [ + { + "description": "Smoothly scroll to follow an object.", + "fullName": "Smooth Camera", + "name": "SmoothCamera", + "objectType": "", + "quickCustomizationVisibility": "hidden", + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onCreated", + "sentence": "", + "events": [ + { + "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": "SmoothCamera::SmoothCamera::SetLeftwardSpeed" + }, + "parameters": [ + "Object", + "Behavior", + "LeftwardSpeed", + "log(1 - )" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetRightwardSpeed" + }, + "parameters": [ + "Object", + "Behavior", + "RightwardSpeed", + "log(1 - )" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetUpwardSpeed" + }, + "parameters": [ + "Object", + "Behavior", + "UpwardSpeed", + "log(1 - )" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetDownwardSpeed" + }, + "parameters": [ + "Object", + "Behavior", + "DownwardSpeed", + "log(1 - )" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetLeftwardSpeedMax" + }, + "parameters": [ + "Object", + "Behavior", + "LeftwardSpeedMax", + "log(1 - )" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetRightwardSpeedMax" + }, + "parameters": [ + "Object", + "Behavior", + "RightwardSpeedMax", + "log(1 - )" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetUpwardSpeedMax" + }, + "parameters": [ + "Object", + "Behavior", + "UpwardSpeedMax", + "log(1 - )" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetDownwardSpeedMax" + }, + "parameters": [ + "Object", + "Behavior", + "DownwardSpeedMax", + "log(1 - )" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetFollowFreeAreaLeft" + }, + "parameters": [ + "Object", + "Behavior", + "FollowFreeAreaLeft", + "log(1 - )" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetFollowFreeAreaRight" + }, + "parameters": [ + "Object", + "Behavior", + "FollowFreeAreaRight", + "log(1 - )" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetFollowFreeAreaTop" + }, + "parameters": [ + "Object", + "Behavior", + "FollowFreeAreaTop", + "log(1 - )" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetFollowFreeAreaBottom" + }, + "parameters": [ + "Object", + "Behavior", + "FollowFreeAreaBottom", + "log(1 - )" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraDelay", + "=", + "CameraDelay" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "doStepPreEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "BooleanVariable" + }, + "parameters": [ + "IsCalledManually", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SmoothCamera::SmoothCamera::DoMoveCameraCloser" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "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": [], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsCalledManually", + "True", + "" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::DoMoveCameraCloser" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "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": "Delaying and forecasting can be used at the same time.\nForecasting only use the positions that are older than the one used for delaying.\nThe behavior uses a position history that is split in 2 arrays:\n- one for delaying the position (from TimeFromStart to TimeFromStart - CamearDelay)\n- one for forecasting the position (from TimeFromStart - CamearDelay to TimeFromStart - CamearDelay - ForecastHistoryDuration" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SmoothCamera::SmoothCamera::UpdateDelayedPosition" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::UpdateForecastedPosition" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ] + }, + { + "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) * 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) * 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) * speed^timeDelta\ncameraX(t) = targetX + (cameraX(t - timeDelta) - targetX) * exp(timeDelta * ln(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": "BooleanVariable" + }, + "parameters": [ + "FollowOnX", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "OldX", + "=", + "CameraX(Object.Layer(), 0)" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CameraX" + }, + "parameters": [ + "", + ">", + "Object.Behavior::FreeAreaRight()", + "Object.Layer()", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetCameraX" + }, + "parameters": [ + "", + "=", + "Object.Behavior::FreeAreaRight()\n+ (CameraX(Object.Layer(), 0) - Object.Behavior::FreeAreaRight())\n* exp(TimeDelta() * LogLeftwardSpeed)", + "Object.Layer()", + "0" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CameraX" + }, + "parameters": [ + "", + "<", + "OldX - LeftwardSpeedMax * TimeDelta()", + "Object.Layer()", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetCameraX" + }, + "parameters": [ + "", + "=", + "OldX - LeftwardSpeedMax * TimeDelta()", + "Object.Layer()", + "0" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CameraX" + }, + "parameters": [ + "", + "<", + "Object.Behavior::FreeAreaLeft()", + "Object.Layer()", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetCameraX" + }, + "parameters": [ + "", + "=", + "Object.Behavior::FreeAreaLeft()\n+ (CameraX(Object.Layer(), 0) - Object.Behavior::FreeAreaLeft())\n* exp(TimeDelta() * LogRightwardSpeed)", + "Object.Layer()", + "0" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CameraX" + }, + "parameters": [ + "", + ">", + "OldX + RightwardSpeedMax * TimeDelta()", + "Object.Layer()", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetCameraX" + }, + "parameters": [ + "", + "=", + "OldX + RightwardSpeedMax * TimeDelta()", + "Object.Layer()", + "0" + ] + } + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "FollowOnY", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "OldY", + "=", + "CameraY(Object.Layer(), 0)" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CameraY" + }, + "parameters": [ + "", + ">", + "Object.Behavior::FreeAreaBottom()", + "Object.Layer()", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetCameraY" + }, + "parameters": [ + "", + "=", + "Object.Behavior::FreeAreaBottom()\n+ (CameraY(Object.Layer(), 0) - Object.Behavior::FreeAreaBottom())\n* exp(TimeDelta() * LogUpwardSpeed)", + "Object.Layer()", + "0" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CameraY" + }, + "parameters": [ + "", + "<", + "OldY - UpwardSpeedMax * TimeDelta()", + "Object.Layer()", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetCameraY" + }, + "parameters": [ + "", + "=", + "OldY - UpwardSpeedMax * TimeDelta()", + "Object.Layer()", + "0" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CameraY" + }, + "parameters": [ + "", + "<", + "Object.Behavior::FreeAreaTop()", + "Object.Layer()", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetCameraY" + }, + "parameters": [ + "", + "=", + "Object.Behavior::FreeAreaTop()\n+ (CameraY(Object.Layer(), 0) - Object.Behavior::FreeAreaTop())\n* exp(TimeDelta() * LogDownwardSpeed)", + "Object.Layer()", + "0" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "CameraY" + }, + "parameters": [ + "", + ">", + "OldY + DownwardSpeedMax * TimeDelta()", + "Object.Layer()", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetCameraY" + }, + "parameters": [ + "", + "=", + "OldY + DownwardSpeedMax * TimeDelta()", + "Object.Layer()", + "0" + ] + } + ] + } + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Delay the camera according to a maximum speed and catch up the delay.", + "fullName": "Wait and catch up", + "functionType": "Action", + "name": "WaitAndCatchUp", + "sentence": "Delay the camera of _PARAM0_ during: _PARAM2_ seconds according to the maximum speed _PARAM3_;_PARAM4_ seconds and catch up in _PARAM5_ seconds", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Maybe the catch-up show be done in constant pixel speed instead of constant time speed." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "WaitingEnd", + "=", + "TimeFromStart() + NewWaitingDuration" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "WaitingSpeedXMax", + "=", + "NewWaitingSpeedXMax" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "WaitingSpeedYMax", + "=", + "NewWaitingSpeedYMax" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraDelayCatchUpDuration", + "=", + "NewCatchUpDuration" + ] + } + ] + }, + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "DebuggerTools::ConsoleLog" + }, + "parameters": [ + "\"Wait and catch up\"", + "\"info\"", + "\"SmoothCamera\"" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Waiting duration (in seconds)", + "name": "NewWaitingDuration", + "type": "expression" + }, + { + "description": "Waiting maximum camera target speed X", + "name": "NewWaitingSpeedXMax", + "type": "expression" + }, + { + "description": "Waiting maximum camera target speed Y", + "name": "NewWaitingSpeedYMax", + "type": "expression" + }, + { + "description": "Catch up duration (in seconds)", + "name": "NewCatchUpDuration", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Draw the targeted and actual camera position.", + "fullName": "Draw debug", + "functionType": "Action", + "name": "DrawDebug", + "sentence": "Draw targeted and actual camera position for _PARAM0_ on _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "PrimitiveDrawing::FillOpacity" + }, + "parameters": [ + "ShapePainter", + "=", + "0" + ] + } + ] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Path used by the forecasting", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Egal" + }, + "parameters": [ + "Object.VariableChildCount(__SmoothCamera.ForecastHistoryTime)", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Index", + "=", + "0" + ] + }, + { + "type": { + "value": "PrimitiveDrawing::OutlineColor" + }, + "parameters": [ + "ShapePainter", + "\"245;166;35\"" + ] + }, + { + "type": { + "value": "PrimitiveDrawing::BeginFillPath" + }, + "parameters": [ + "ShapePainter", + "Object.Variable(__SmoothCamera.ForecastHistoryX[0])", + "Object.Variable(__SmoothCamera.ForecastHistoryY[0])" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Repeat", + "repeatExpression": "Object.VariableChildCount(__SmoothCamera.ForecastHistoryX)", + "conditions": [], + "actions": [ + { + "type": { + "value": "PrimitiveDrawing::PathLineTo" + }, + "parameters": [ + "ShapePainter", + "Object.Variable(__SmoothCamera.ForecastHistoryX[Index])", + "Object.Variable(__SmoothCamera.ForecastHistoryY[Index])" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Index", + "+", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "PrimitiveDrawing::EndFillPath" + }, + "parameters": [ + "ShapePainter" + ] + } + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Follow-free area.", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "FollowFreeAreaLeft", + "!=", + "0" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "FollowFreeAreaRight", + "!=", + "0" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "FollowFreeAreaTop", + "!=", + "0" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "FollowFreeAreaBottom", + "!=", + "0" + ] + } + ] + } + ], + "actions": [ + { + "type": { + "value": "PrimitiveDrawing::OutlineColor" + }, + "parameters": [ + "ShapePainter", + "\"126;211;33\"" + ] + }, + { + "type": { + "value": "PrimitiveDrawing::Rectangle" + }, + "parameters": [ + "ShapePainter", + "Object.Behavior::FreeAreaLeft() - 1", + "Object.Behavior::FreeAreaTop() - 1", + "Object.Behavior::FreeAreaRight() + 1", + "Object.Behavior::FreeAreaBottom() + 1" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Linear regression vector used by the forecasting.", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "PrimitiveDrawing::OutlineColor" + }, + "parameters": [ + "ShapePainter", + "\"208;2;27\"" + ] + }, + { + "type": { + "value": "PrimitiveDrawing::LineV2" + }, + "parameters": [ + "ShapePainter", + "ProjectedOldestX", + "ProjectedOldestY", + "ProjectedNewestX", + "ProjectedNewestY", + "1" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Targeted and actual camera position", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "PrimitiveDrawing::Circle" + }, + "parameters": [ + "ShapePainter", + "ForecastedX", + "ForecastedY", + "3" + ] + }, + { + "type": { + "value": "PrimitiveDrawing::LineV2" + }, + "parameters": [ + "ShapePainter", + "CameraX(Object.Layer(), 0)", + "CameraY(Object.Layer(), 0) - 4", + "CameraX(Object.Layer(), 0)", + "CameraY(Object.Layer(), 0) + 4", + "1" + ] + }, + { + "type": { + "value": "PrimitiveDrawing::LineV2" + }, + "parameters": [ + "ShapePainter", + "CameraX(Object.Layer(), 0) - 4", + "CameraY(Object.Layer(), 0)", + "CameraX(Object.Layer(), 0) + 4", + "CameraY(Object.Layer(), 0)", + "1" + ] + } + ] + } + ], + "parameters": [] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Shape painter", + "name": "ShapePainter", + "supplementaryInformation": "PrimitiveDrawing::Drawer", + "type": "objectList" + } + ], + "objectGroups": [] + }, + { + "description": "Enable or disable the following on X axis.", + "fullName": "Follow on X", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetFollowOnX", + "sentence": "The camera follows _PARAM0_ on X axis: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "FollowOnX", + "False", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "FollowOnX", + "True", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Follow on X axis", + "name": "Value", + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "Enable or disable the following on Y axis.", + "fullName": "Follow on Y", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetFollowOnY", + "sentence": "The camera follows _PARAM0_ on Y axis: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "FollowOnY", + "False", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "FollowOnY", + "True", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Follow on Y axis", + "name": "Value", + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "Change the camera follow free area right border.", + "fullName": "Follow free area right border", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetFollowFreeAreaRight", + "sentence": "Change the camera follow free area right border of _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "FollowFreeAreaRight", + "=", + "max(0, Value)" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Follow free area right border", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the camera follow free area left border.", + "fullName": "Follow free area left border", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetFollowFreeAreaLeft", + "sentence": "Change the camera follow free area left border of _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "FollowFreeAreaLeft", + "=", + "max(0, Value)" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Follow free area left border", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the camera follow free area top border.", + "fullName": "Follow free area top border", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetFollowFreeAreaTop", + "sentence": "Change the camera follow free area top border of _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "FollowFreeAreaTop", + "=", + "max(0, Value)" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Follow free area top border", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the camera follow free area bottom border.", + "fullName": "Follow free area bottom border", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetFollowFreeAreaBottom", + "sentence": "Change the camera follow free area bottom border of _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "FollowFreeAreaBottom", + "=", + "max(0, Value)" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Follow free area bottom border", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the camera leftward maximum speed (in pixels per second).", + "fullName": "Leftward maximum speed", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetLeftwardSpeedMax", + "sentence": "Change the camera leftward maximum speed of _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "LeftwardSpeedMax", + "=", + "max(0, Value)" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Leftward maximum speed (in pixels per second)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the camera rightward maximum speed (in pixels per second).", + "fullName": "Rightward maximum speed", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetRightwardSpeedMax", + "sentence": "Change the camera rightward maximum speed of _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "RightwardSpeedMax", + "=", + "max(0, Value)" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Rightward maximum speed (in pixels per second)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the camera upward maximum speed (in pixels per second).", + "fullName": "Upward maximum speed", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetUpwardSpeedMax", + "sentence": "Change the camera upward maximum speed of _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "UpwardSpeedMax", + "=", + "max(0, Value)" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Upward maximum speed (in pixels per second)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the camera downward maximum speed (in pixels per second).", + "fullName": "Downward maximum speed", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetDownwardSpeedMax", + "sentence": "Change the camera downward maximum speed of _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "DownwardSpeedMax", + "=", + "max(0, Value)" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Downward maximum speed (in pixels per second)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the camera leftward catch-up speed (in ratio per second).", + "fullName": "Leftward catch-up speed", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetLeftwardSpeed", + "sentence": "Change the camera leftward catch-up speed of _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "LeftwardSpeed", + "=", + "clamp(0, 1, Value)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "LogLeftwardSpeed", + "=", + "log(1 - Value)" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Leftward catch-up speed (in ratio per second)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the camera rightward catch-up speed (in ratio per second).", + "fullName": "Rightward catch-up speed", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetRightwardSpeed", + "sentence": "Change the camera rightward catch-up speed of _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "RightwardSpeed", + "=", + "clamp(0, 1, Value)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "LogRightwardSpeed", + "=", + "log(1 - Value)" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Rightward catch-up speed (in ratio per second)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the camera downward catch-up speed (in ratio per second).", + "fullName": "Downward catch-up speed", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetDownwardSpeed", + "sentence": "Change the camera downward catch-up speed of _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "DownwardSpeed", + "=", + "clamp(0, 1, Value)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "LogDownwardSpeed", + "=", + "log(1 - Value)" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Downward catch-up speed (in ratio per second)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the camera upward catch-up speed (in ratio per second).", + "fullName": "Upward catch-up speed", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetUpwardSpeed", + "sentence": "Change the camera upward catch-up speed of _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "UpwardSpeed", + "=", + "clamp(0, 1, Value)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "LogUpwardSpeed", + "=", + "log(1 - Value)" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Upward catch-up speed (in ratio per second)", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the camera offset on X axis of the object. This is not the current difference between the object and the camera position.", + "fullName": "Camera offset X", + "functionType": "ExpressionAndCondition", + "group": "Camera configuration", + "name": "OffsetX", + "sentence": "the camera offset on X axis", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "CameraOffsetX" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "OffsetX", + "name": "SetOffsetXOp", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraOffsetX", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Change the camera offset on X axis of an object.", + "fullName": "Camera Offset X", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetOffsetX", + "private": true, + "sentence": "Change the camera offset on X axis of _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Deprecated use SetOffsetXOp instead." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetOffsetXOp" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "Value", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Camera offset X", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the camera offset on Y axis of the object. This is not the current difference between the object and the camera position.", + "fullName": "Camera offset Y", + "functionType": "ExpressionAndCondition", + "group": "Camera configuration", + "name": "OffsetY", + "sentence": "the camera offset on Y axis", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "CameraOffsetY" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "OffsetY", + "name": "SetOffsetYOp", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraOffsetY", + "=", + "Value" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Change the camera offset on Y axis of an object.", + "fullName": "Camera Offset Y", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetOffsetY", + "private": true, + "sentence": "Change the camera offset on Y axis of _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Deprecated use SetOffsetYOp instead." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetOffsetYOp" + }, + "parameters": [ + "Object", + "Behavior", + "=", + "CameraOffsetY", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Camera offset Y", + "name": "CameraOffsetY", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the camera forecast time (in seconds).", + "fullName": "Forecast time", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetForecastTime", + "sentence": "Change the camera forecast time of _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastTime", + "=", + "min(0, Value)" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Forecast time", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Change the camera delay (in seconds).", + "fullName": "Camera delay", + "functionType": "Action", + "group": "Camera configuration", + "name": "SetCameraDelay", + "sentence": "Change the camera delay of _PARAM0_: _PARAM2_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraDelay", + "=", + "max(0, Value)" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Camera delay", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Return follow free area left border X.", + "fullName": "Free area left", + "functionType": "Expression", + "group": "Private", + "name": "FreeAreaLeft", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ForecastedX + CameraOffsetX - FollowFreeAreaLeft" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Return follow free area right border X.", + "fullName": "Free area right", + "functionType": "Expression", + "group": "Private", + "name": "FreeAreaRight", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ForecastedX + CameraOffsetX + FollowFreeAreaRight" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Return follow free area bottom border Y.", + "fullName": "Free area bottom", + "functionType": "Expression", + "group": "Private", + "name": "FreeAreaBottom", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ForecastedY + CameraOffsetY + FollowFreeAreaBottom" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Return follow free area top border Y.", + "fullName": "Free area top", + "functionType": "Expression", + "group": "Private", + "name": "FreeAreaTop", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ForecastedY + CameraOffsetY - FollowFreeAreaTop" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Update delayed position and delayed history. This is called in doStepPreEvents.", + "fullName": "Update delayed position", + "functionType": "Action", + "group": "Private", + "name": "UpdateDelayedPosition", + "private": true, + "sentence": "Update delayed position and delayed history of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Add the previous position to have enough (2) positions to evaluate the extra delay for waiting mode." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "SmoothCamera::SmoothCamera::IsWaiting" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "value": "Egal" + }, + "parameters": [ + "Object.VariableChildCount(__SmoothCamera.ObjectTime)", + "=", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "ObjectVariablePushNumber" + }, + "parameters": [ + "Object", + "__SmoothCamera.ObjectTime", + "TimeFromStart()" + ] + }, + { + "type": { + "value": "ObjectVariablePushNumber" + }, + "parameters": [ + "Object", + "__SmoothCamera.ObjectX", + "DelayedCenterX" + ] + }, + { + "type": { + "value": "ObjectVariablePushNumber" + }, + "parameters": [ + "Object", + "__SmoothCamera.ObjectY", + "DelayedCenterY" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Use the object center when no delay is asked." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "DelayedCenterX", + "=", + "Object.CenterX()" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "DelayedCenterY", + "=", + "Object.CenterY()" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "SmoothCamera::SmoothCamera::IsDelayed" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SmoothCamera::SmoothCamera::AddForecastHistoryPosition" + }, + "parameters": [ + "Object", + "Behavior", + "TimeFromStart()", + "Object.CenterX()", + "Object.CenterY()", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "SmoothCamera::SmoothCamera::IsDelayed" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::IsWaiting" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ] + } + ], + "actions": [ + { + "type": { + "value": "ObjectVariablePushNumber" + }, + "parameters": [ + "Object", + "__SmoothCamera.ObjectTime", + "TimeFromStart()" + ] + }, + { + "type": { + "value": "ObjectVariablePushNumber" + }, + "parameters": [ + "Object", + "__SmoothCamera.ObjectX", + "Object.CenterX()" + ] + }, + { + "type": { + "value": "ObjectVariablePushNumber" + }, + "parameters": [ + "Object", + "__SmoothCamera.ObjectY", + "Object.CenterY()" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Remove history entries that are too old to be useful for delaying and pass it to the history for forecasting." + }, + { + "infiniteLoopWarning": true, + "type": "BuiltinCommonInstructions::While", + "whileConditions": [ + { + "type": { + "value": "Egal" + }, + "parameters": [ + "Object.VariableChildCount(__SmoothCamera.ObjectTime)", + ">=", + "2" + ] + }, + { + "type": { + "value": "VarObjet" + }, + "parameters": [ + "Object", + "__SmoothCamera.ObjectTime[1]", + "<", + "TimeFromStart() - Object.Behavior::CurrentDelay()" + ] + } + ], + "conditions": [], + "actions": [ + { + "type": { + "value": "SmoothCamera::SmoothCamera::AddForecastHistoryPosition" + }, + "parameters": [ + "Object", + "Behavior", + "Object.Variable(__SmoothCamera.ObjectTime[0])", + "Object.Variable(__SmoothCamera.ObjectX[0])", + "Object.Variable(__SmoothCamera.ObjectY[0])", + "" + ] + }, + { + "type": { + "value": "ObjectVariableRemoveAt" + }, + "parameters": [ + "Object", + "__SmoothCamera.ObjectTime", + "0" + ] + }, + { + "type": { + "value": "ObjectVariableRemoveAt" + }, + "parameters": [ + "Object", + "__SmoothCamera.ObjectX", + "0" + ] + }, + { + "type": { + "value": "ObjectVariableRemoveAt" + }, + "parameters": [ + "Object", + "__SmoothCamera.ObjectY", + "0" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Don't move the camera if there is not enough history." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "DelayedCenterX", + "=", + "Object.Variable(__SmoothCamera.ObjectX[0])" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "DelayedCenterY", + "=", + "Object.Variable(__SmoothCamera.ObjectY[0])" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Egal" + }, + "parameters": [ + "Object.VariableChildCount(__SmoothCamera.ObjectTime)", + ">=", + "2" + ] + }, + { + "type": { + "value": "VarObjet" + }, + "parameters": [ + "Object", + "__SmoothCamera.ObjectTime[0]", + "<", + "TimeFromStart() - Object.Behavior::CurrentDelay()" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Add the extra delay that could be needed to respect the speed limit in waiting mode.\n\nspeedRatio = min(speedMaxX / historySpeedX, speedMaxY / historySpeedY)\ndelay += min(0, timeDelta * (1 - speedRatio))" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "SmoothCamera::SmoothCamera::IsWaiting" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraExtraDelay", + "+", + "max(0, TimeDelta() * (1 - min(WaitingSpeedXMax * abs(Object.Variable(__SmoothCamera.ObjectX[1]) - Object.Variable(__SmoothCamera.ObjectX[0])), WaitingSpeedYMax * abs(Object.Variable(__SmoothCamera.ObjectY[1]) - Object.Variable(__SmoothCamera.ObjectY[0]))) / (Object.Variable(__SmoothCamera.ObjectTime[1]) - Object.Variable(__SmoothCamera.ObjectTime[0]))))" + ] + } + ], + "events": [ + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "DebuggerTools::ConsoleLog" + }, + "parameters": [ + "\"Extra delay: \" + ToString(CameraExtraDelay)", + "\"info\"", + "\"SmoothCamera\"" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "The time with delay is now between the first 2 indexes" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "DelayedCenterX", + "=", + "lerp(Object.Variable(__SmoothCamera.ObjectX[1]), Object.Variable(__SmoothCamera.ObjectX[0]), ((TimeFromStart() - Object.Behavior::CurrentDelay()) - Object.Variable(__SmoothCamera.ObjectTime[1])) / (Object.Variable(__SmoothCamera.ObjectTime[0]) - Object.Variable(__SmoothCamera.ObjectTime[1])))" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "DelayedCenterY", + "=", + "lerp(Object.Variable(__SmoothCamera.ObjectY[1]), Object.Variable(__SmoothCamera.ObjectY[0]), ((TimeFromStart() - Object.Behavior::CurrentDelay()) - Object.Variable(__SmoothCamera.ObjectTime[1])) / (Object.Variable(__SmoothCamera.ObjectTime[0]) - Object.Variable(__SmoothCamera.ObjectTime[1])))" + ] + } + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "SmoothCamera::SmoothCamera::IsDelayed" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "inverted": true, + "value": "SmoothCamera::SmoothCamera::IsWaiting" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "ObjectVariableClearChildren" + }, + "parameters": [ + "Object", + "__SmoothCamera.ObjectTime" + ] + }, + { + "type": { + "value": "ObjectVariableClearChildren" + }, + "parameters": [ + "Object", + "__SmoothCamera.ObjectX" + ] + }, + { + "type": { + "value": "ObjectVariableClearChildren" + }, + "parameters": [ + "Object", + "__SmoothCamera.ObjectY" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "SmoothCamera::SmoothCamera::IsWaiting" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Once" + }, + "parameters": [] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraDelayCatchUpSpeed", + "=", + "CameraExtraDelay / CameraDelayCatchUpDuration" + ] + } + ], + "events": [ + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "DebuggerTools::ConsoleLog" + }, + "parameters": [ + "\"Start to catch up\"", + "\"info\"", + "\"SmoothCamera\"" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "SmoothCamera::SmoothCamera::IsWaiting" + }, + "parameters": [ + "Object", + "Behavior", + "" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "CameraExtraDelay", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "CameraExtraDelay", + "=", + "max(0, CameraExtraDelay -CameraDelayCatchUpSpeed * TimeDelta())" + ] + } + ], + "events": [ + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "DebuggerTools::ConsoleLog" + }, + "parameters": [ + "\"Catching up delay: \" + ToString(CameraExtraDelay)", + "\"info\"", + "\"SmoothCamera\"" + ] + } + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the camera following target is delayed from the object.", + "fullName": "Camera is delayed", + "functionType": "Condition", + "name": "IsDelayed", + "private": true, + "sentence": "The camera of _PARAM0_ is delayed", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Egal" + }, + "parameters": [ + "Object.Behavior::CurrentDelay()", + ">", + "0" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Return the current camera delay.", + "fullName": "Current delay", + "functionType": "Expression", + "name": "CurrentDelay", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "CameraDelay + CameraExtraDelay" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the camera following is waiting at a reduced speed.", + "fullName": "Camera is waiting", + "functionType": "Condition", + "name": "IsWaiting", + "private": true, + "sentence": "The camera of _PARAM0_ is waiting", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "WaitingEnd", + ">", + "TimeFromStart()" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Add a position to the history for forecasting. This is called 2 times in UpadteDelayedPosition.", + "fullName": "Add forecast history position", + "functionType": "Action", + "group": "Private", + "name": "AddForecastHistoryPosition", + "private": true, + "sentence": "Add the time:_PARAM2_ and position: _PARAM3_; _PARAM4_ to the forecast history of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "ForecastHistoryDuration", + ">", + "0" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "ForecastTime", + ">", + "0" + ] + } + ] + } + ], + "actions": [ + { + "type": { + "value": "ObjectVariablePushNumber" + }, + "parameters": [ + "Object", + "__SmoothCamera.ForecastHistoryTime", + "Time" + ] + }, + { + "type": { + "value": "ObjectVariablePushNumber" + }, + "parameters": [ + "Object", + "__SmoothCamera.ForecastHistoryX", + "ObjectX" + ] + }, + { + "type": { + "value": "ObjectVariablePushNumber" + }, + "parameters": [ + "Object", + "__SmoothCamera.ForecastHistoryY", + "ObjectY" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Remove history entries that are too old to be useful.\nKeep at least 2 positions because no forecast can be done with less positions." + }, + { + "infiniteLoopWarning": true, + "type": "BuiltinCommonInstructions::While", + "whileConditions": [ + { + "type": { + "value": "Egal" + }, + "parameters": [ + "Object.VariableChildCount(__SmoothCamera.ForecastHistoryTime)", + ">=", + "3" + ] + }, + { + "type": { + "value": "VarObjet" + }, + "parameters": [ + "Object", + "__SmoothCamera.ForecastHistoryTime[0]", + "<", + "TimeFromStart() - CameraDelay - CameraExtraDelay - ForecastHistoryDuration" + ] + } + ], + "conditions": [], + "actions": [ + { + "type": { + "value": "ObjectVariableRemoveAt" + }, + "parameters": [ + "Object", + "__SmoothCamera.ForecastHistoryTime", + "0" + ] + }, + { + "type": { + "value": "ObjectVariableRemoveAt" + }, + "parameters": [ + "Object", + "__SmoothCamera.ForecastHistoryX", + "0" + ] + }, + { + "type": { + "value": "ObjectVariableRemoveAt" + }, + "parameters": [ + "Object", + "__SmoothCamera.ForecastHistoryY", + "0" + ] + } + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "Time", + "name": "Time", + "type": "expression" + }, + { + "description": "Object X", + "name": "ObjectX", + "type": "expression" + }, + { + "description": "Object Y", + "name": "ObjectY", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Update forecasted position. This is called in doStepPreEvents.", + "fullName": "Update forecasted position", + "functionType": "Action", + "group": "Private", + "name": "UpdateForecastedPosition", + "private": true, + "sentence": "Update forecasted position of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastedX", + "=", + "DelayedCenterX" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastedY", + "=", + "DelayedCenterY" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Simple linear regression\ny = A * x + B\n\nA = Covariance / VarianceX\nB = MeanY - A * MeanX\n\nNote than we could use only one position every N positions to reduce the process time,\nbut if we really need efficient process JavaScript and circular queues are a must." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Egal" + }, + "parameters": [ + "Object.VariableChildCount(__SmoothCamera.ForecastHistoryTime)", + ">=", + "2" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "ForecastHistoryDuration", + ">", + "0" + ] + }, + { + "type": { + "value": "NumberVariable" + }, + "parameters": [ + "ForecastTime", + ">", + "0" + ] + } + ] + } + ], + "actions": [], + "events": [ + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Mean X", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastHistoryMeanX", + "=", + "0" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Index", + "=", + "0" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Repeat", + "repeatExpression": "Object.VariableChildCount(__SmoothCamera.ForecastHistoryX)", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastHistoryMeanX", + "+", + "Object.Variable(__SmoothCamera.ForecastHistoryX[Index])" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Index", + "+", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastHistoryMeanX", + "/", + "Object.VariableChildCount(__SmoothCamera.ForecastHistoryX)" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Mean Y", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastHistoryMeanY", + "=", + "0" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Index", + "=", + "0" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Repeat", + "repeatExpression": "Object.VariableChildCount(__SmoothCamera.ForecastHistoryY)", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastHistoryMeanY", + "+", + "Object.Variable(__SmoothCamera.ForecastHistoryY[Index])" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Index", + "+", + "1" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastHistoryMeanY", + "/", + "Object.VariableChildCount(__SmoothCamera.ForecastHistoryY)" + ] + } + ] + }, + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "DebuggerTools::ConsoleLog" + }, + "parameters": [ + "\"Mean: \" + ToString(ForecastHistoryMeanX) + \" \" + ToString(ForecastHistoryMeanY)", + "", + "" + ] + } + ] + } + ], + "parameters": [] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Variance and Covariance", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "VarianceX = sum((X[i] - MeanX)²)\nVarianceY = sum((Y[i] - MeanY)²)\nCovariance = sum((X[i] - MeanX) * (Y[i] - MeanY))" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastHistoryVarianceX", + "=", + "0" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastHistoryVarianceY", + "=", + "0" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastHistoryCovariance", + "=", + "0" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Index", + "=", + "0" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Repeat", + "repeatExpression": "Object.VariableChildCount(__SmoothCamera.ForecastHistoryX)", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastHistoryVarianceX", + "+", + "pow(Object.Variable(__SmoothCamera.ForecastHistoryX[Index]) - ForecastHistoryMeanX, 2)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastHistoryVarianceY", + "+", + "pow(Object.Variable(__SmoothCamera.ForecastHistoryY[Index]) - ForecastHistoryMeanY, 2)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastHistoryCovariance", + "+", + "(Object.Variable(__SmoothCamera.ForecastHistoryX[Index]) - ForecastHistoryMeanX)\n*\n(Object.Variable(__SmoothCamera.ForecastHistoryY[Index]) - ForecastHistoryMeanY)" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Index", + "+", + "1" + ] + } + ] + }, + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "DebuggerTools::ConsoleLog" + }, + "parameters": [ + "\"Variances: \" + ToString(ForecastHistoryVarianceX) + \" \" + ToString(ForecastHistoryVarianceY) + \" \" + ToString(ForecastHistoryCovariance)", + "\"info\"", + "\"SmoothCamera\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Egal" + }, + "parameters": [ + "abs(ForecastHistoryVarianceX)", + "<", + "1" + ] + }, + { + "type": { + "value": "Egal" + }, + "parameters": [ + "abs(ForecastHistoryVarianceY)", + "<", + "1" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastedX", + "=", + "DelayedCenterX" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastedY", + "=", + "DelayedCenterY" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "Egal" + }, + "parameters": [ + "abs(ForecastHistoryVarianceX)", + ">=", + "1" + ] + }, + { + "type": { + "value": "Egal" + }, + "parameters": [ + "abs(ForecastHistoryVarianceY)", + ">=", + "1" + ] + } + ] + } + ], + "actions": [], + "events": [ + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Linear function parameters", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "y = A * x + B\n\nA = Covariance / VarianceX\nB = MeanY - A * MeanX" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Egal" + }, + "parameters": [ + "abs(ForecastHistoryVarianceX)", + ">=", + "abs(ForecastHistoryVarianceY)" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastHistoryLinearA", + "=", + "ForecastHistoryCovariance / ForecastHistoryVarianceX" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastHistoryLinearB", + "=", + "ForecastHistoryMeanY - ForecastHistoryLinearA * ForecastHistoryMeanX" + ] + } + ], + "events": [ + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "DebuggerTools::ConsoleLog" + }, + "parameters": [ + "\"Linear: \" + ToString(ForecastHistoryLinearA) + \" \" + ToString(ForecastHistoryLinearB)", + "\"info\"", + "\"SmoothCamera\"" + ] + } + ] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Projection", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SmoothCamera::SmoothCamera::ProjectHistoryEnds" + }, + "parameters": [ + "Object", + "Behavior", + "Object.Variable(__SmoothCamera.ForecastHistoryX[0])", + "Object.Variable(__SmoothCamera.ForecastHistoryY[0])", + "Object.Variable(__SmoothCamera.ForecastHistoryX[Object.VariableChildCount(__SmoothCamera.ForecastHistoryX) - 1])", + "Object.Variable(__SmoothCamera.ForecastHistoryY[Object.VariableChildCount(__SmoothCamera.ForecastHistoryY) - 1])", + "" + ] + } + ] + } + ], + "parameters": [] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Axis permutation to avoid a ratio between 2 numbers near 0." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "Egal" + }, + "parameters": [ + "abs(ForecastHistoryVarianceX)", + "<", + "abs(ForecastHistoryVarianceY)" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastHistoryLinearA", + "=", + "ForecastHistoryCovariance / ForecastHistoryVarianceY" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastHistoryLinearB", + "=", + "ForecastHistoryMeanX - ForecastHistoryLinearA * ForecastHistoryMeanY" + ] + } + ], + "events": [ + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "DebuggerTools::ConsoleLog" + }, + "parameters": [ + "\"Linear: \" + ToString(ForecastHistoryLinearA) + \" \" + ToString(ForecastHistoryLinearB)", + "\"info\"", + "\"SmoothCamera\"" + ] + } + ] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Projection", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SmoothCamera::SmoothCamera::ProjectHistoryEnds" + }, + "parameters": [ + "Object", + "Behavior", + "Object.Variable(__SmoothCamera.ForecastHistoryY[0])", + "Object.Variable(__SmoothCamera.ForecastHistoryX[0])", + "Object.Variable(__SmoothCamera.ForecastHistoryY[Object.VariableChildCount(__SmoothCamera.ForecastHistoryY) - 1])", + "Object.Variable(__SmoothCamera.ForecastHistoryX[Object.VariableChildCount(__SmoothCamera.ForecastHistoryX) - 1])", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Permute back axis" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Index", + "=", + "ProjectedOldestX" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ProjectedOldestX", + "=", + "ProjectedOldestY" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ProjectedOldestY", + "=", + "Index" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Index", + "=", + "ProjectedNewestX" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ProjectedNewestX", + "=", + "ProjectedNewestY" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ProjectedNewestY", + "=", + "Index" + ] + } + ] + } + ], + "parameters": [] + }, + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "DebuggerTools::ConsoleLog" + }, + "parameters": [ + "\"Oldest: \" + ToString(ProjectedOldestX) + \" \" + ToString(ProjectedOldestY)", + "\"info\"", + "\"SmoothCamera\"" + ] + } + ] + }, + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "DebuggerTools::ConsoleLog" + }, + "parameters": [ + "\"Newest: \" + ToString(ProjectedNewestX) + \" \" + ToString(ProjectedNewestY)", + "\"info\"", + "\"SmoothCamera\"" + ] + } + ] + } + ] + }, + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Forecasted position", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastedX", + "=", + "ProjectedNewestX + ( ProjectedNewestX - ProjectedOldestX) * Object.Behavior::ForecastTimeRatio()" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ForecastedY", + "=", + "ProjectedNewestY + ( ProjectedNewestY - ProjectedOldestY) * Object.Behavior::ForecastTimeRatio()" + ] + } + ] + }, + { + "disabled": true, + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "DebuggerTools::ConsoleLog" + }, + "parameters": [ + "\"Forecasted: \" + ToString(ForecastedX) + \" \" + ToString(ForecastedY)", + "\"info\"", + "\"SmoothCamera\"" + ] + } + ] + } + ], + "parameters": [] + } + ], + "parameters": [] + } + ] + } + ], + "parameters": [] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "Project history ends position to have the vector on the line from linear regression. This function is only called by UpdateForecastedPosition.", + "fullName": "Project history ends", + "functionType": "Action", + "group": "Private", + "name": "ProjectHistoryEnds", + "private": true, + "sentence": "Project history oldest: _PARAM2_;_PARAM3_ and newest position: _PARAM4_;_PARAM5_ of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Perpendicular line:\npA = -1/a; \npB = -pA * x + y\n\nIntersection:\n/ ProjectedY = a * ProjectedX + b\n\\ ProjectedY = pA * ProjectedX + b\n\nSolution that is cleaned out from indeterminism (like 0 / 0 or infinity / infinity):\nProjectedX= (x + (y - b) * a) / (a² + 1)\nProjectedY = y + (x * a - y + b) / (a² + 1)" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ProjectedNewestX", + "=", + "(NewestX + (NewestY - ForecastHistoryLinearB) * ForecastHistoryLinearA) / (1 + pow(ForecastHistoryLinearA, 2))" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ProjectedNewestY", + "=", + "NewestY + (NewestX * ForecastHistoryLinearA - NewestY \n+ ForecastHistoryLinearB) / (1 + pow(ForecastHistoryLinearA, 2))" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ProjectedOldestX", + "=", + "(OldestX + (OldestY - ForecastHistoryLinearB) * ForecastHistoryLinearA) / (1 + pow(ForecastHistoryLinearA, 2))" + ] + }, + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ProjectedOldestY", + "=", + "OldestY + (OldestX * ForecastHistoryLinearA - OldestY \n+ ForecastHistoryLinearB) / (1 + pow(ForecastHistoryLinearA, 2))" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + }, + { + "description": "OldestX", + "name": "OldestX", + "type": "expression" + }, + { + "description": "OldestY", + "name": "OldestY", + "type": "expression" + }, + { + "description": "Newest X", + "name": "NewestX", + "type": "expression" + }, + { + "description": "Newest Y", + "name": "NewestY", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Return the ratio between forecast time and the duration of the history. This function is only called by UpdateForecastedPosition.", + "fullName": "Forecast time ratio", + "functionType": "Expression", + "group": "Private", + "name": "ForecastTimeRatio", + "private": true, + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "- ForecastTime / (Object.Variable(__SmoothCamera.ForecastHistoryTime[0]) - Object.Variable(__SmoothCamera.ForecastHistoryTime[Object.VariableChildCount(__SmoothCamera.ForecastHistoryTime) - 1]))" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothCamera", + "type": "behavior" + } + ], + "objectGroups": [] + } + ], + "propertyDescriptors": [ + { + "value": "0.9", + "type": "Number", + "label": "Leftward catch-up speed (in ratio per second)", + "group": "Catch-up speed", + "name": "LeftwardSpeed" + }, + { + "value": "0.9", + "type": "Number", + "label": "Rightward catch-up speed (in ratio per second)", + "group": "Catch-up speed", + "name": "RightwardSpeed" + }, + { + "value": "0.9", + "type": "Number", + "label": "Upward catch-up speed (in ratio per second)", + "group": "Catch-up speed", + "name": "UpwardSpeed" + }, + { + "value": "0.9", + "type": "Number", + "label": "Downward catch-up speed (in ratio per second)", + "group": "Catch-up speed", + "name": "DownwardSpeed" + }, + { + "value": "true", + "type": "Boolean", + "label": "Follow on X axis", + "name": "FollowOnX" + }, + { + "value": "true", + "type": "Boolean", + "label": "Follow on Y axis", + "name": "FollowOnY" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Follow free area left border", + "group": "Position", + "advanced": true, + "name": "FollowFreeAreaLeft" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Follow free area right border", + "group": "Position", + "advanced": true, + "name": "FollowFreeAreaRight" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Follow free area top border", + "group": "Position", + "advanced": true, + "name": "FollowFreeAreaTop" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Follow free area bottom border", + "group": "Position", + "advanced": true, + "name": "FollowFreeAreaBottom" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Camera offset X", + "group": "Position", + "advanced": true, + "name": "CameraOffsetX" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Camera offset Y", + "group": "Position", + "advanced": true, + "name": "CameraOffsetY" + }, + { + "value": "0", + "type": "Number", + "unit": "Second", + "label": "Camera delay", + "group": "Timing", + "deprecated": true, + "name": "CameraDelay" + }, + { + "value": "0", + "type": "Number", + "unit": "Second", + "label": "Forecast time", + "group": "Timing", + "deprecated": true, + "name": "ForecastTime" + }, + { + "value": "0", + "type": "Number", + "unit": "Second", + "label": "Forecast history duration", + "group": "Timing", + "deprecated": true, + "name": "ForecastHistoryDuration" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "LogLeftwardSpeed" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "LogRightwardSpeed" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "LogDownwardSpeed" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "LogUpwardSpeed" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "DelayedCenterX" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "DelayedCenterY" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "ForecastHistoryMeanX" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "ForecastHistoryMeanY" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "ForecastHistoryVarianceX" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "ForecastHistoryCovariance" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "ForecastHistoryLinearA" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "ForecastHistoryLinearB" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "ForecastedX" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "ForecastedY" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "ProjectedNewestX" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "ProjectedNewestY" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "ProjectedOldestX" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "ProjectedOldestY" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "ForecastHistoryVarianceY" + }, + { + "value": "", + "type": "Number", + "label": "Index (local variable)", + "hidden": true, + "name": "Index" + }, + { + "value": "0", + "type": "Number", + "label": "", + "hidden": true, + "name": "CameraDelayCatchUpSpeed" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "CameraExtraDelay" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "WaitingSpeedXMax" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "WaitingSpeedYMax" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "WaitingEnd" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "CameraDelayCatchUpDuration" + }, + { + "value": "9000", + "type": "Number", + "unit": "PixelSpeed", + "label": "Leftward maximum speed", + "group": "Maximum speed", + "advanced": true, + "name": "LeftwardSpeedMax" + }, + { + "value": "9000", + "type": "Number", + "unit": "PixelSpeed", + "label": "Rightward maximum speed", + "group": "Maximum speed", + "advanced": true, + "name": "RightwardSpeedMax" + }, + { + "value": "9000", + "type": "Number", + "unit": "PixelSpeed", + "label": "Upward maximum speed", + "group": "Maximum speed", + "advanced": true, + "name": "UpwardSpeedMax" + }, + { + "value": "9000", + "type": "Number", + "unit": "PixelSpeed", + "label": "Downward maximum speed", + "group": "Maximum speed", + "advanced": true, + "name": "DownwardSpeedMax" + }, + { + "value": "", + "type": "Number", + "label": "OldX (local variable)", + "hidden": true, + "name": "OldX" + }, + { + "value": "", + "type": "Number", + "label": "OldY (local variable)", + "hidden": true, + "name": "OldY" + }, + { + "value": "", + "type": "Boolean", + "label": "", + "hidden": true, + "name": "IsCalledManually" + } + ], + "sharedPropertyDescriptors": [] + }, + { + "description": "Smoothly scroll to follow a character and stabilize the camera when jumping.", + "fullName": "Smooth platformer camera", + "name": "SmoothPlatformerCamera", + "objectType": "", + "quickCustomizationVisibility": "hidden", + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "doStepPreEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "inverted": true, + "value": "PlatformBehavior::IsJumping" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + }, + { + "type": { + "inverted": true, + "value": "PlatformBehavior::IsFalling" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + } + ], + "actions": [ + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetFollowFreeAreaBottom" + }, + "parameters": [ + "Object", + "SmoothCamera", + "FloorFollowFreeAreaTop", + "" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetFollowFreeAreaTop" + }, + "parameters": [ + "Object", + "SmoothCamera", + "FloorFollowFreeAreaBottom", + "" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetUpwardSpeed" + }, + "parameters": [ + "Object", + "SmoothCamera", + "FloorUpwardSpeed", + "" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetDownwardSpeed" + }, + "parameters": [ + "Object", + "SmoothCamera", + "FloorDownwardSpeed", + "" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetUpwardSpeedMax" + }, + "parameters": [ + "Object", + "SmoothCamera", + "FloorUpwardSpeedMax", + "" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetDownwardSpeedMax" + }, + "parameters": [ + "Object", + "SmoothCamera", + "FloorDownwardSpeedMax", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::Or" + }, + "parameters": [], + "subInstructions": [ + { + "type": { + "value": "PlatformBehavior::IsJumping" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + }, + { + "type": { + "value": "PlatformBehavior::IsFalling" + }, + "parameters": [ + "Object", + "PlatformerCharacter" + ] + } + ] + } + ], + "actions": [ + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetFollowFreeAreaBottom" + }, + "parameters": [ + "Object", + "SmoothCamera", + "AirFollowFreeAreaTop", + "" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetFollowFreeAreaTop" + }, + "parameters": [ + "Object", + "SmoothCamera", + "AirFollowFreeAreaBottom", + "" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetUpwardSpeed" + }, + "parameters": [ + "Object", + "SmoothCamera", + "AirUpwardSpeed", + "" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetDownwardSpeed" + }, + "parameters": [ + "Object", + "SmoothCamera", + "AirDownwardSpeed", + "" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetUpwardSpeedMax" + }, + "parameters": [ + "Object", + "SmoothCamera", + "AirUpwardSpeedMax", + "" + ] + }, + { + "type": { + "value": "SmoothCamera::SmoothCamera::SetDownwardSpeedMax" + }, + "parameters": [ + "Object", + "SmoothCamera", + "AirDownwardSpeedMax", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "SmoothCamera::SmoothPlatformerCamera", + "type": "behavior" + } + ], + "objectGroups": [] + } + ], + "propertyDescriptors": [ + { + "value": "", + "type": "Behavior", + "label": "Platformer character behavior", + "extraInformation": [ + "PlatformBehavior::PlatformerObjectBehavior" + ], + "choices": [], + "name": "PlatformerCharacter" + }, + { + "value": "", + "type": "Behavior", + "label": "Smooth camera behavior", + "extraInformation": [ + "SmoothCamera::SmoothCamera" + ], + "choices": [], + "name": "SmoothCamera" + }, + { + "value": "", + "type": "Number", + "label": "", + "hidden": true, + "name": "JumpOriginY" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Follow free area top in the air", + "group": "Position", + "name": "AirFollowFreeAreaTop" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Follow free area bottom in the air", + "group": "Position", + "name": "AirFollowFreeAreaBottom" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Follow free area top on the floor", + "group": "Position", + "name": "FloorFollowFreeAreaTop" + }, + { + "value": "0", + "type": "Number", + "unit": "Pixel", + "label": "Follow free area bottom on the floor", + "group": "Position", + "name": "FloorFollowFreeAreaBottom" + }, + { + "value": "0.95", + "type": "Number", + "label": "Upward speed in the air (in ratio per second)", + "group": "Catch-up speed", + "name": "AirUpwardSpeed" + }, + { + "value": "0.95", + "type": "Number", + "label": "Downward speed in the air (in ratio per second)", + "group": "Catch-up speed", + "name": "AirDownwardSpeed" + }, + { + "value": "0.9", + "type": "Number", + "label": "Upward speed on the floor (in ratio per second)", + "group": "Catch-up speed", + "name": "FloorUpwardSpeed" + }, + { + "value": "0.9", + "type": "Number", + "label": "Downward speed on the floor (in ratio per second)", + "group": "Catch-up speed", + "name": "FloorDownwardSpeed" + }, + { + "value": "9000", + "type": "Number", + "unit": "PixelSpeed", + "label": "Upward maximum speed in the air", + "group": "Maximum speed", + "name": "AirUpwardSpeedMax" + }, + { + "value": "9000", + "type": "Number", + "unit": "PixelSpeed", + "label": "Downward maximum speed in the air", + "group": "Maximum speed", + "name": "AirDownwardSpeedMax" + }, + { + "value": "9000", + "type": "Number", + "unit": "PixelSpeed", + "label": "Upward maximum speed on the floor", + "group": "Maximum speed", + "name": "FloorUpwardSpeedMax" + }, + { + "value": "9000", + "type": "Number", + "unit": "PixelSpeed", + "label": "Downward maximum speed on the floor", + "group": "Maximum speed", + "name": "FloorDownwardSpeedMax" + } + ], + "sharedPropertyDescriptors": [] + } + ], + "eventsBasedObjects": [] + }, + { + "author": "", + "category": "Camera", + "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": "Move the camera to look at an object from a given distance.", + "version": "1.8.0", + "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": [ + "if (gdjs.__thirdPersonCameraExtension) {", + " 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));", + "}", + "", + "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": [] + } + ], + "eventsBasedBehaviors": [ + { + "description": "Smoothly follow an object at a distance.", + "fullName": "Third person camera", + "name": "ThirdPersonCamera", + "objectType": "", + "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", + "False", + "" + ] + } + ], + "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", + "True", + "" + ] + } + ] + } + ], + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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", + "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": [] + } + ], + "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" + } + ], + "sharedPropertyDescriptors": [] + } + ], + "eventsBasedObjects": [] + }, + { + "author": "", + "category": "General", + "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": [] + } + ], + "eventsBasedBehaviors": [], + "eventsBasedObjects": [] + }, + { + "author": "", + "category": "General", + "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": [] } - ] + ], + "eventsBasedBehaviors": [], + "eventsBasedObjects": [] } ], "externalLayouts": [ @@ -26967,8 +36342,8 @@ "persistentUuid": "e13b9837-4ab4-475d-a1ab-5f727ead59da", "width": 1024, "x": 0, - "y": 192, - "z": 80, + "y": 160, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -26984,8 +36359,8 @@ "persistentUuid": "556b77d2-6dc6-417c-8192-60501f4ec644", "width": 1024, "x": 0, - "y": 192, - "z": -80, + "y": 320, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -27001,8 +36376,8 @@ "persistentUuid": "9cf32052-9522-451a-b8b2-564788873f4a", "width": 1024, "x": 0, - "y": 192, - "z": 240, + "y": 0, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -27034,8 +36409,8 @@ "persistentUuid": "1af66394-f474-4aec-8fab-861cd0542aa6", "width": 96, "x": 688, - "y": 152, - "z": 160, + "y": 240, + "z": 40, "zOrder": 5, "numberProperties": [], "stringProperties": [], @@ -27051,7 +36426,8 @@ "persistentUuid": "1bfd08fc-6991-4146-b94f-3355a73b0a77", "width": 96, "x": 688, - "y": 152, + "y": 400, + "z": 40, "zOrder": 5, "numberProperties": [], "stringProperties": [], @@ -27067,8 +36443,8 @@ "persistentUuid": "5143812a-0b9e-4b26-9e94-51032ca22316", "width": 96, "x": 688, - "y": 152, - "z": 320, + "y": 80, + "z": 40, "zOrder": 5, "numberProperties": [], "stringProperties": [], @@ -27077,14 +36453,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "3eba5768-f945-4e72-92c7-c0098f6bb675", "width": 64, "x": 352, - "y": 128, - "z": 160, + "y": 240, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27093,14 +36470,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "35a8297d-c18b-4daa-af27-6b89f69bfa83", "width": 64, "x": 512, - "y": 128, - "z": 320, + "y": 80, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27109,13 +36487,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "81b0a462-89cc-4903-ac03-5082f0c6c04a", "width": 64, "x": 192, - "y": 128, + "y": 400, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27132,8 +36512,9 @@ "gridColor": 10401023, "gridAlpha": 0.8, "snap": true, - "zoomFactor": 0.5117784035210186, - "windowMask": false + "zoomFactor": 0.5843784410740942, + "windowMask": false, + "selectedLayer": "" } }, { @@ -27150,8 +36531,8 @@ "persistentUuid": "e13b9837-4ab4-475d-a1ab-5f727ead59da", "width": 1024, "x": 0, - "y": 192, - "z": 80, + "y": 160, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -27167,8 +36548,8 @@ "persistentUuid": "556b77d2-6dc6-417c-8192-60501f4ec644", "width": 1024, "x": 0, - "y": 192, - "z": -80, + "y": 320, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -27184,8 +36565,8 @@ "persistentUuid": "9cf32052-9522-451a-b8b2-564788873f4a", "width": 1024, "x": 0, - "y": 192, - "z": 240, + "y": 0, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -27217,8 +36598,8 @@ "persistentUuid": "9d761244-9671-4777-aafa-e4b653bd0d00", "width": 96, "x": 688, - "y": 152, - "z": 160, + "y": 240, + "z": 40, "zOrder": 5, "numberProperties": [], "stringProperties": [], @@ -27227,14 +36608,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "d71c8cd5-3553-4875-8783-4401ba0642a1", "width": 64, "x": 512, - "y": 128, - "z": 160, + "y": 240, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27243,14 +36625,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "c7c73351-9fb2-482c-807d-cd1d7d6b0ac1", "width": 64, "x": 352, - "y": 128, - "z": 320, + "y": 80, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27259,14 +36642,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "0751c083-6231-411d-b880-3bc317f19826", "width": 64, "x": 192, - "y": 128, - "z": 320, + "y": 80, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27275,13 +36659,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "0c6ce33b-2b5a-45d8-8ee6-c59f14676f78", "width": 64, "x": 192, - "y": 128, + "y": 400, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27290,13 +36676,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "577c0e44-3523-4cf6-a403-1cd5c08f467d", "width": 64, "x": 352, - "y": 128, + "y": 400, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27314,7 +36702,8 @@ "gridAlpha": 0.8, "snap": true, "zoomFactor": 0.4633111824513984, - "windowMask": false + "windowMask": false, + "selectedLayer": "" } }, { @@ -27331,8 +36720,8 @@ "persistentUuid": "e13b9837-4ab4-475d-a1ab-5f727ead59da", "width": 1024, "x": 0, - "y": 192, - "z": 80, + "y": 160, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -27348,8 +36737,8 @@ "persistentUuid": "556b77d2-6dc6-417c-8192-60501f4ec644", "width": 1024, "x": 0, - "y": 192, - "z": -80, + "y": 320, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -27365,8 +36754,8 @@ "persistentUuid": "9cf32052-9522-451a-b8b2-564788873f4a", "width": 1024, "x": 0, - "y": 192, - "z": 240, + "y": 0, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -27391,14 +36780,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "3cfb0b79-5527-430b-9f58-65653ac8171a", "width": 64, "x": 64, - "y": 128, - "z": 160, + "y": 240, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27407,13 +36797,14 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "7d9777f9-a5dd-4456-8a50-63a8b9392b26", "width": 64, "x": 224, - "y": 32, + "y": 240, "z": 160, "zOrder": 6, "numberProperties": [], @@ -27423,13 +36814,14 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "9e3958af-4338-4888-bed2-f1169dc6fb42", "width": 64, "x": 352, - "y": 32, + "y": 240, "z": 160, "zOrder": 6, "numberProperties": [], @@ -27439,31 +36831,33 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "ab4e4d4a-effd-4855-a1e5-b24676a489ca", "width": 64, "x": 896, - "y": 128, - "z": 160, + "y": 240, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], "initialVariables": [] }, { - "angle": -45, + "angle": 0, "customSize": true, - "depth": 160, - "height": 136, + "depth": 136, + "height": 160, "layer": "", "name": "GroundElevated", "persistentUuid": "ddd2936c-ded2-4fec-a216-cd5b2b57df3f", + "rotationY": -45, "width": 136, "x": 124, - "y": 124, - "z": 80, + "y": 160, + "z": -68, "zOrder": 8, "numberProperties": [], "stringProperties": [], @@ -27472,14 +36866,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "34804264-c3a8-47bc-94dc-f88e3f3498b6", "width": 64, "x": 768, - "y": 128, - "z": 160, + "y": 240, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27488,13 +36883,14 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "c6eb1b47-f6a6-423b-ae9a-99b620249b4f", "width": 64, "x": 608, - "y": 32, + "y": 240, "z": 160, "zOrder": 6, "numberProperties": [], @@ -27504,13 +36900,14 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "f0880dec-c78e-4d3e-afca-bdcaaaf20e9a", "width": 64, "x": 480, - "y": 32, + "y": 240, "z": 160, "zOrder": 6, "numberProperties": [], @@ -27520,15 +36917,14 @@ { "angle": 0, "customSize": true, - "depth": 160, - "height": 96, + "depth": 96, + "height": 160, "layer": "", "name": "GroundElevated", "persistentUuid": "270f9ebf-1b95-4114-8c7f-985a2d6768b0", "width": 448, "x": 192, - "y": 96, - "z": 80, + "y": 160, "zOrder": 8, "numberProperties": [], "stringProperties": [], @@ -27545,8 +36941,9 @@ "gridColor": 10401023, "gridAlpha": 0.8, "snap": true, - "zoomFactor": 0.8700232859857299, - "windowMask": false + "zoomFactor": 0.7130377630690404, + "windowMask": false, + "selectedLayer": "" } }, { @@ -27563,8 +36960,8 @@ "persistentUuid": "e13b9837-4ab4-475d-a1ab-5f727ead59da", "width": 1024, "x": 0, - "y": 192, - "z": 80, + "y": 160, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -27580,8 +36977,8 @@ "persistentUuid": "556b77d2-6dc6-417c-8192-60501f4ec644", "width": 480, "x": 544, - "y": 192, - "z": -80, + "y": 320, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -27597,8 +36994,8 @@ "persistentUuid": "9cf32052-9522-451a-b8b2-564788873f4a", "width": 480, "x": 544, - "y": 192, - "z": 240, + "y": 0, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -27630,8 +37027,8 @@ "persistentUuid": "0f9ab667-093e-4cb1-9767-9758486f0ba8", "width": 224, "x": 0, - "y": 192, - "z": 240, + "y": 0, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -27647,8 +37044,8 @@ "persistentUuid": "83b20036-e69d-4a55-b2dc-2db1a4e59eca", "width": 224, "x": 0, - "y": 192, - "z": -80, + "y": 320, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -27657,14 +37054,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "82379e82-5bfc-46c5-8555-5ed9b8b1cfae", "width": 64, "x": 864, - "y": 128, - "z": 320, + "y": 80, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27673,14 +37071,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "c734aa0b-23af-42f6-b29a-b36ecc5a2a7e", "width": 64, "x": 160, - "y": 128, - "z": 320, + "y": 80, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27689,14 +37088,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "381ac4c6-c06c-4350-960a-19b78344e899", "width": 64, "x": 320, - "y": 32, - "z": 320, + "y": 80, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27705,14 +37105,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "11031e02-89f9-41bd-93ca-f601c6b0664a", "width": 64, "x": 448, - "y": 32, - "z": 320, + "y": 80, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27721,13 +37122,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "c8d43540-339c-40b4-b806-c73cb214cb19", "width": 64, "x": 160, - "y": 128, + "y": 400, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27736,13 +37139,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "1a342051-9852-40a1-8516-a98d7b17fbf4", "width": 64, "x": 320, - "y": 32, + "y": 400, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27751,13 +37156,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "c3b62340-8c68-45ca-950e-b7908e16d8ad", "width": 64, "x": 448, - "y": 32, + "y": 400, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27766,13 +37173,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "465d2b3c-4a71-4ccf-8f3d-8d8a6ab87bb4", "width": 64, "x": 864, - "y": 128, + "y": 400, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27781,13 +37190,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "a8e3ee1b-f547-41d4-9d77-ca2e17f53fb3", "width": 64, "x": 608, - "y": 128, + "y": 400, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27796,14 +37207,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "4db5dd8e-a5ac-45c6-9cd4-4bd905afea02", "width": 64, "x": 608, - "y": 128, - "z": 320, + "y": 80, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27812,14 +37224,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "87fbeae7-576a-471c-b62a-9b7e8b1f9e3b", "width": 64, "x": 736, - "y": 128, - "z": 320, + "y": 80, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27828,13 +37241,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "1dc84750-9423-46c6-893f-eb737fe2717b", "width": 64, "x": 736, - "y": 128, + "y": 400, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27869,8 +37284,8 @@ "persistentUuid": "e13b9837-4ab4-475d-a1ab-5f727ead59da", "width": 1024, "x": 0, - "y": 192, - "z": 80, + "y": 160, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -27886,8 +37301,8 @@ "persistentUuid": "556b77d2-6dc6-417c-8192-60501f4ec644", "width": 1024, "x": 0, - "y": 192, - "z": -80, + "y": 320, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -27903,8 +37318,8 @@ "persistentUuid": "9cf32052-9522-451a-b8b2-564788873f4a", "width": 1024, "x": 0, - "y": 192, - "z": 240, + "y": 0, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -27936,8 +37351,8 @@ "persistentUuid": "1af66394-f474-4aec-8fab-861cd0542aa6", "width": 96, "x": 688, - "y": 152, - "z": 160, + "y": 240, + "z": 40, "zOrder": 5, "numberProperties": [], "stringProperties": [], @@ -27953,7 +37368,8 @@ "persistentUuid": "1bfd08fc-6991-4146-b94f-3355a73b0a77", "width": 96, "x": 688, - "y": 152, + "y": 400, + "z": 40, "zOrder": 5, "numberProperties": [], "stringProperties": [], @@ -27969,8 +37385,8 @@ "persistentUuid": "5143812a-0b9e-4b26-9e94-51032ca22316", "width": 96, "x": 688, - "y": 152, - "z": 320, + "y": 80, + "z": 40, "zOrder": 5, "numberProperties": [], "stringProperties": [], @@ -27979,14 +37395,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "3eba5768-f945-4e72-92c7-c0098f6bb675", "width": 64, "x": 352, - "y": 128, - "z": 160, + "y": 240, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -27995,13 +37412,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "ccbe5c16-fd57-4f55-b58c-c4f8b95eb171", "width": 64, "x": 512, - "y": 128, + "y": 400, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28010,14 +37429,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "35a8297d-c18b-4daa-af27-6b89f69bfa83", "width": 64, "x": 192, - "y": 128, - "z": 320, + "y": 80, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28035,7 +37455,8 @@ "gridAlpha": 0.8, "snap": true, "zoomFactor": 0.4789341884535246, - "windowMask": false + "windowMask": false, + "selectedLayer": "" } }, { @@ -28052,8 +37473,8 @@ "persistentUuid": "e13b9837-4ab4-475d-a1ab-5f727ead59da", "width": 256, "x": 0, - "y": 192, - "z": 80, + "y": 160, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -28085,8 +37506,8 @@ "persistentUuid": "0f9ab667-093e-4cb1-9767-9758486f0ba8", "width": 1024, "x": 0, - "y": 192, - "z": 240, + "y": 0, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -28102,8 +37523,8 @@ "persistentUuid": "83b20036-e69d-4a55-b2dc-2db1a4e59eca", "width": 1024, "x": 0, - "y": 192, - "z": -80, + "y": 320, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -28119,8 +37540,8 @@ "persistentUuid": "35843c40-c437-4151-8486-1272fb8734c6", "width": 448, "x": 576, - "y": 192, - "z": 80, + "y": 160, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -28129,14 +37550,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "100d8ba2-873b-4e80-9cef-fcfb5c723528", "width": 64, "x": 192, - "y": 128, - "z": 160, + "y": 240, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28145,13 +37567,14 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "0859f0c1-0208-4487-a8d8-3a9d38905937", "width": 64, "x": 352, - "y": 32, + "y": 240, "z": 160, "zOrder": 6, "numberProperties": [], @@ -28161,13 +37584,14 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "d6dda353-d34a-4200-973b-61f501d2a7ce", "width": 64, "x": 480, - "y": 32, + "y": 240, "z": 160, "zOrder": 6, "numberProperties": [], @@ -28177,14 +37601,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "0ef18cb7-7258-488a-a15b-59ee2419bb6a", "width": 64, "x": 896, - "y": 128, - "z": 160, + "y": 240, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28193,14 +37618,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "4390fffc-67ee-453f-8853-53bd9b201f81", "width": 64, "x": 640, - "y": 128, - "z": 160, + "y": 240, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28209,14 +37635,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "d7b5a171-ef87-47e5-be4f-68ba46f958b1", "width": 64, "x": 768, - "y": 128, - "z": 160, + "y": 240, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28234,7 +37661,8 @@ "gridAlpha": 0.8, "snap": true, "zoomFactor": 0.43357743047023733, - "windowMask": false + "windowMask": false, + "selectedLayer": "" } }, { @@ -28251,8 +37679,8 @@ "persistentUuid": "e13b9837-4ab4-475d-a1ab-5f727ead59da", "width": 1024, "x": 0, - "y": 192, - "z": 80, + "y": 160, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -28268,8 +37696,8 @@ "persistentUuid": "556b77d2-6dc6-417c-8192-60501f4ec644", "width": 1024, "x": 0, - "y": 192, - "z": -80, + "y": 320, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -28285,8 +37713,8 @@ "persistentUuid": "9cf32052-9522-451a-b8b2-564788873f4a", "width": 1024, "x": 0, - "y": 192, - "z": 240, + "y": 0, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -28311,15 +37739,14 @@ { "angle": 0, "customSize": true, - "depth": 160, - "height": 96, + "depth": 96, + "height": 160, "layer": "", "name": "GroundElevated", "persistentUuid": "ddd2936c-ded2-4fec-a216-cd5b2b57df3f", "width": 768, "x": 96, - "y": 96, - "z": -80, + "y": 320, "zOrder": 8, "numberProperties": [], "stringProperties": [], @@ -28328,15 +37755,14 @@ { "angle": 0, "customSize": true, - "depth": 160, - "height": 96, + "depth": 96, + "height": 160, "layer": "", "name": "GroundElevated", "persistentUuid": "03b1b229-88a8-4251-9391-06709d296f53", "width": 768, "x": 96, - "y": 96, - "z": 240, + "y": 0, "zOrder": 8, "numberProperties": [], "stringProperties": [], @@ -28345,13 +37771,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "437548f9-00c6-477f-aa24-cfe99d6f4a83", "width": 64, "x": 128, - "y": 32, + "y": 400, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28360,13 +37788,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "1a3088ee-944d-46f7-9a29-2859c16808e0", "width": 64, "x": 384, - "y": 32, + "y": 400, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28375,13 +37805,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "a1508b08-5925-403b-862c-f4edddf7a490", "width": 64, "x": 512, - "y": 32, + "y": 400, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28390,13 +37822,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "30fdc1dc-7fc3-42fe-a1fe-50c35e07c3c4", "width": 64, "x": 640, - "y": 32, + "y": 400, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28405,14 +37839,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "b900ce41-dd28-4f7f-84e5-611057c1e184", "width": 64, "x": 128, - "y": 32, - "z": 320, + "y": 80, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28421,14 +37856,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "f5fcdb75-c5ea-4edc-a8a5-c68c09a63762", "width": 64, "x": 384, - "y": 32, - "z": 320, + "y": 80, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28437,14 +37873,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "e843c8c8-1b7a-4938-b6f8-10fe240021c5", "width": 64, "x": 512, - "y": 32, - "z": 320, + "y": 80, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28453,14 +37890,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "ef30178d-045b-471e-b5a5-1d4107d438a2", "width": 64, "x": 640, - "y": 32, - "z": 320, + "y": 80, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28469,13 +37907,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "05de4693-f941-4e43-8826-f359c013667d", "width": 64, "x": 256, - "y": 32, + "y": 400, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28484,14 +37924,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "8bf17fd3-c9a0-4510-87e4-6aee6172a45b", "width": 64, "x": 256, - "y": 32, - "z": 320, + "y": 80, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28500,13 +37941,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "3880eaa6-c754-4fe7-882e-1e8c2a92413d", "width": 64, "x": 768, - "y": 32, + "y": 400, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28515,48 +37958,51 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "ddd4b84d-d080-41b0-a7aa-ed4e7b007bd2", "width": 64, "x": 768, - "y": 32, - "z": 320, + "y": 80, + "z": 160, "zOrder": 6, "numberProperties": [], "stringProperties": [], "initialVariables": [] }, { - "angle": -45, + "angle": 0, "customSize": true, - "depth": 160, - "height": 136, + "depth": 136, + "height": 160, "layer": "", "name": "GroundElevated", "persistentUuid": "60e4c3e1-04d9-4c37-87b4-4f90dcb8e276", + "rotationY": -45, "width": 136, "x": 28, - "y": 124, - "z": -80, + "y": 320, + "z": -68, "zOrder": 8, "numberProperties": [], "stringProperties": [], "initialVariables": [] }, { - "angle": -45, + "angle": 0, "customSize": true, - "depth": 160, - "height": 136, + "depth": 136, + "height": 160, "layer": "", "name": "GroundElevated", "persistentUuid": "773fd33b-a388-4680-86dc-d09e126a9abc", + "rotationY": -45, "width": 136, "x": 28, - "y": 124, - "z": 240, + "y": 0, + "z": -68, "zOrder": 8, "numberProperties": [], "stringProperties": [], @@ -28574,7 +38020,8 @@ "gridAlpha": 0.8, "snap": true, "zoomFactor": 0.3325387091250777, - "windowMask": false + "windowMask": false, + "selectedLayer": "" } }, { @@ -28591,8 +38038,8 @@ "persistentUuid": "e13b9837-4ab4-475d-a1ab-5f727ead59da", "width": 96, "x": 0, - "y": 192, - "z": 80, + "y": 160, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -28608,8 +38055,8 @@ "persistentUuid": "556b77d2-6dc6-417c-8192-60501f4ec644", "width": 1024, "x": 0, - "y": 192, - "z": -80, + "y": 320, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -28625,8 +38072,8 @@ "persistentUuid": "9cf32052-9522-451a-b8b2-564788873f4a", "width": 1024, "x": 0, - "y": 192, - "z": 240, + "y": 0, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -28651,13 +38098,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "437548f9-00c6-477f-aa24-cfe99d6f4a83", "width": 64, "x": 128, - "y": 128, + "y": 400, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28666,13 +38115,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "1a3088ee-944d-46f7-9a29-2859c16808e0", "width": 64, "x": 384, - "y": 128, + "y": 400, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28681,13 +38132,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "a1508b08-5925-403b-862c-f4edddf7a490", "width": 64, "x": 512, - "y": 128, + "y": 400, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28696,14 +38149,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "b900ce41-dd28-4f7f-84e5-611057c1e184", "width": 64, "x": 128, - "y": 128, - "z": 320, + "y": 80, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28712,14 +38166,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "f5fcdb75-c5ea-4edc-a8a5-c68c09a63762", "width": 64, "x": 384, - "y": 128, - "z": 320, + "y": 80, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28728,14 +38183,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "e843c8c8-1b7a-4938-b6f8-10fe240021c5", "width": 64, "x": 512, - "y": 128, - "z": 320, + "y": 80, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28744,13 +38200,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "05de4693-f941-4e43-8826-f359c013667d", "width": 64, "x": 256, - "y": 128, + "y": 400, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28759,14 +38217,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "8bf17fd3-c9a0-4510-87e4-6aee6172a45b", "width": 64, "x": 256, - "y": 128, - "z": 320, + "y": 80, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28782,7 +38241,8 @@ "persistentUuid": "25318c82-d38a-4c3c-9a2f-47f536716a2f", "width": 96, "x": 784, - "y": 152, + "y": 400, + "z": 40, "zOrder": 5, "numberProperties": [], "stringProperties": [], @@ -28798,8 +38258,8 @@ "persistentUuid": "30d33585-77b7-415c-9c0e-94f8954f7b02", "width": 96, "x": 784, - "y": 152, - "z": 320, + "y": 80, + "z": 40, "zOrder": 5, "numberProperties": [], "stringProperties": [], @@ -28817,7 +38277,8 @@ "gridAlpha": 0.8, "snap": true, "zoomFactor": 0.5290357402156846, - "windowMask": false + "windowMask": false, + "selectedLayer": "" } }, { @@ -28834,8 +38295,8 @@ "persistentUuid": "e13b9837-4ab4-475d-a1ab-5f727ead59da", "width": 1024, "x": 0, - "y": 192, - "z": 80, + "y": 160, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -28867,8 +38328,8 @@ "persistentUuid": "0f9ab667-093e-4cb1-9767-9758486f0ba8", "width": 96, "x": 0, - "y": 192, - "z": 240, + "y": 0, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -28884,8 +38345,8 @@ "persistentUuid": "83b20036-e69d-4a55-b2dc-2db1a4e59eca", "width": 96, "x": 0, - "y": 192, - "z": -80, + "y": 320, + "z": -160, "zOrder": 4, "numberProperties": [], "stringProperties": [], @@ -28894,14 +38355,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "100d8ba2-873b-4e80-9cef-fcfb5c723528", "width": 64, "x": 128, - "y": 128, - "z": 160, + "y": 240, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28910,14 +38372,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "0859f0c1-0208-4487-a8d8-3a9d38905937", "width": 64, "x": 256, - "y": 128, - "z": 160, + "y": 240, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28926,14 +38389,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "d6dda353-d34a-4200-973b-61f501d2a7ce", "width": 64, "x": 512, - "y": 128, - "z": 160, + "y": 240, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28942,14 +38406,15 @@ { "angle": 0, "customSize": false, - "height": 64, + "depth": 64, + "height": 0, "layer": "", "name": "Coin", "persistentUuid": "1c95f325-9227-4ad4-9c22-70c0456833bc", "width": 64, "x": 384, - "y": 128, - "z": 160, + "y": 240, + "z": 64, "zOrder": 6, "numberProperties": [], "stringProperties": [], @@ -28965,8 +38430,8 @@ "persistentUuid": "f60aba27-0158-42c5-af61-9e6c43ed3598", "width": 96, "x": 784, - "y": 152, - "z": 160, + "y": 240, + "z": 40, "zOrder": 5, "numberProperties": [], "stringProperties": [], @@ -28984,7 +38449,75 @@ "gridAlpha": 0.8, "snap": true, "zoomFactor": 0.5843784410740929, - "windowMask": false + "windowMask": false, + "selectedLayer": "" + } + }, + { + "associatedLayout": "Game", + "name": "UI", + "instances": [ + { + "angle": 0, + "customSize": false, + "height": 0, + "layer": "UI", + "name": "TutorialText", + "persistentUuid": "087a624c-171a-421d-a2dd-5b54611922c5", + "width": 0, + "x": 8, + "y": 1218, + "zOrder": 10, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "UI", + "name": "HighScoreLabel", + "persistentUuid": "3f919c94-710e-4161-8a9e-abfc5ed304a3", + "width": 0, + "x": 8, + "y": 57, + "zOrder": 13, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "customSize": false, + "height": 0, + "keepRatio": true, + "layer": "UI", + "name": "ScoreLabel", + "persistentUuid": "c1c22f40-11ee-4af4-bc5d-9225b642d8c1", + "width": 0, + "x": 8, + "y": 0, + "zOrder": 12, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + } + ], + "editionSettings": { + "grid": false, + "gridType": "rectangular", + "gridWidth": 32, + "gridHeight": 32, + "gridOffsetX": 0, + "gridOffsetY": 0, + "gridColor": 10401023, + "gridAlpha": 0.8, + "snap": false, + "zoomFactor": 0.546875, + "windowMask": false, + "selectedLayer": "" } } ] diff --git a/examples/3d-lane-runner/assets/TrailDropSide.png b/examples/3d-lane-runner/assets/TrailDropSide.png new file mode 100644 index 000000000..043819fba Binary files /dev/null and b/examples/3d-lane-runner/assets/TrailDropSide.png differ