diff --git a/.gitignore b/.gitignore index 5a272b424..60fca0582 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,9 @@ /dist *.autosave +# The GDevelop build the gameplay test runner downloads (hundreds of MB). +/.gameplay-tests-work + # Artefacts written next to a game by the gameplay test runner. gameplay-test-results.json gameplay-test-screenshots/ diff --git a/examples/3d-light-playground/3d-light-playground.json b/examples/3d-light-playground/3d-light-playground.json new file mode 100644 index 000000000..4db9148f4 --- /dev/null +++ b/examples/3d-light-playground/3d-light-playground.json @@ -0,0 +1,8781 @@ +{ + "firstLayout": "Sun and Shadows", + "gdVersion": { + "build": 279, + "major": 5, + "minor": 6, + "revision": 0 + }, + "properties": { + "adaptGameResolutionAtRuntime": true, + "antialiasingMode": "MSAA", + "antialisingEnabledOnMobile": false, + "folderProject": false, + "orientation": "landscape", + "packageName": "io.gdevelop.examples.lightplayground", + "pixelsRounding": false, + "projectUuid": "7b1f6f4e-9c2a-4c37-9d21-0f5a3b8c41d2", + "scaleMode": "linear", + "sizeOnStartupMode": "", + "templateSlug": "", + "version": "1.0.0", + "name": "3D light playground", + "description": "A playground for the 3D lights: the directional light and its shadows, coloured point lights, spot lights, and many lights at once.", + "author": "", + "windowWidth": 1280, + "windowHeight": 720, + "latestCompilationDirectory": "", + "maxFPS": 60, + "minFPS": 20, + "verticalSync": false, + "platformSpecificAssets": { + "android-icon-144": "", + "android-icon-192": "", + "android-icon-36": "", + "android-icon-48": "", + "android-icon-72": "", + "android-icon-96": "", + "android-windowSplashScreenAnimatedIcon": "", + "desktop-icon-512": "", + "ios-icon-100": "", + "ios-icon-1024": "", + "ios-icon-114": "", + "ios-icon-120": "", + "ios-icon-144": "", + "ios-icon-152": "", + "ios-icon-167": "", + "ios-icon-180": "", + "ios-icon-20": "", + "ios-icon-29": "", + "ios-icon-40": "", + "ios-icon-50": "", + "ios-icon-57": "", + "ios-icon-58": "", + "ios-icon-60": "", + "ios-icon-72": "", + "ios-icon-76": "", + "ios-icon-80": "", + "ios-icon-87": "" + }, + "loadingScreen": { + "backgroundColor": 0, + "backgroundFadeInDuration": 0.2, + "backgroundImageResourceName": "", + "gdevelopLogoStyle": "light", + "logoAndProgressFadeInDuration": 0.2, + "logoAndProgressLogoFadeInDelay": 0, + "minDuration": 1.5, + "progressBarColor": 16777215, + "progressBarHeight": 20, + "progressBarMaxWidth": 200, + "progressBarMinWidth": 40, + "progressBarWidthPercent": 30, + "showGDevelopSplash": true, + "showProgressBar": true + }, + "watermark": { + "placement": "bottom-left", + "showWatermark": true + }, + "authorIds": [], + "authorUsernames": [], + "categories": [], + "playableDevices": [ + "mobile" + ], + "extensionProperties": [], + "platforms": [ + { + "name": "GDevelop JS platform" + } + ], + "currentPlatform": "GDevelop JS platform" + }, + "resources": { + "resources": [ + { + "file": "assets/LightPlaygroundSurface.png", + "kind": "image", + "metadata": "", + "name": "assets/LightPlaygroundSurface.png", + "userAdded": false, + "smoothed": true, + "alwaysLoaded": false + } + ], + "resourceFolders": [] + }, + "objects": [], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [] + }, + "objectsGroups": [], + "variables": [], + "layouts": [ + { + "b": 190, + "disableInputWhenNotFocused": true, + "mangledName": "Sun_and_Shadows", + "name": "Sun and Shadows", + "r": 120, + "standardSortMethod": true, + "stopSoundsOnStartup": true, + "title": "", + "v": 150, + "uiSettings": { + "grid": false, + "gridType": "rectangular", + "gridWidth": 32, + "gridHeight": 32, + "gridOffsetX": 0, + "gridOffsetY": 0, + "gridColor": 10401023, + "gridAlpha": 0.8, + "snap": true, + "zoomFactor": 0.35, + "windowMask": false + }, + "objectsGroups": [], + "variables": [], + "instances": [ + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 20, + "height": 2400, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Ground", + "persistentUuid": "b090e0d0-06ca-2518-98fa-c63d498a7de4", + "width": 2400, + "x": -1200, + "y": -1200, + "z": -20, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 460, + "height": 110, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Pillar", + "persistentUuid": "2b7f7d92-a9e2-c4c8-bb48-5d71fcd16b84", + "width": 110, + "x": -55, + "y": -55, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 320, + "height": 60, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Backdrop", + "persistentUuid": "19ddede8-766d-ab48-ce0a-80a2f23bc81d", + "width": 900, + "x": -450, + "y": -900, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "3fdda8ff-dc0e-7c1a-f754-d933f0f4d28a", + "width": 140, + "x": -520, + "y": -420, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "fd2c00d2-250c-def9-2903-66670a15015c", + "width": 140, + "x": 380, + "y": -480, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "57363f1e-d65d-3e58-ee58-8c3137384388", + "width": 140, + "x": -600, + "y": 320, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "87224692-c2ad-dcb7-b6b7-71b0135f42b6", + "width": 140, + "x": 460, + "y": 300, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "eafbcc09-5057-5dca-8e2d-a35b8111fa27", + "width": 140, + "x": -80, + "y": -640, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "f818a1a3-593b-2d99-78b2-ca893240b86d", + "width": 140, + "x": -60, + "y": 480, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + } + ], + "objects": [ + { + "assetStoreId": "", + "name": "Ground", + "persistentUuid": "e46f1434-2c55-2bca-2ccf-742ed8e26b67", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 2400, + "height": 2400, + "depth": 20, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "170;175;180", + "isCastingShadow": false, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "Crate", + "persistentUuid": "df5c6f4b-aedc-6655-8ef5-10c3d9b3294a", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 140, + "height": 140, + "depth": 140, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "196;146;92", + "isCastingShadow": true, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "Pillar", + "persistentUuid": "bcda4ad2-b8bf-a7ee-c150-3cb4ff8649d2", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 110, + "height": 110, + "depth": 460, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "205;208;212", + "isCastingShadow": true, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "Backdrop", + "persistentUuid": "405800cc-89d5-f501-5a8d-23977b035d4d", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 900, + "height": 60, + "depth": 320, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "150;154;162", + "isCastingShadow": true, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Ground" + }, + { + "objectName": "Crate" + }, + { + "objectName": "Pillar" + }, + { + "objectName": "Backdrop" + } + ] + }, + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "// Frame the props the same way in every scene and on every run, so the", + "// screenshots the gameplay tests take can be compared between versions.", + "if (!runtimeScene.__cameraPlaced) {", + " runtimeScene.__cameraPlaced = true;", + " gdjs.evtTools.camera.setCameraX(runtimeScene, 0, '', 0);", + " gdjs.evtTools.camera.setCameraY(runtimeScene, 1450, '', 0);", + " gdjs.scene3d.camera.setCameraZ(runtimeScene, 880, '', 0);", + " gdjs.scene3d.camera.setCameraRotationX(runtimeScene, 59, '', 0);", + " gdjs.scene3d.camera.setCameraRotationY(runtimeScene, 0, '', 0);", + "}" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "layers": [ + { + "ambientLightColorR": 120, + "ambientLightColorG": 130, + "ambientLightColorB": 150, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "", + "renderingType": "", + "visibility": true, + "cameras": [ + { + "defaultSize": true, + "defaultViewport": true, + "height": 0, + "viewportBottom": 1, + "viewportLeft": 0, + "viewportRight": 1, + "viewportTop": 0, + "width": 0 + } + ], + "effects": [ + { + "effectType": "Scene3D::AmbientLight", + "name": "Ambient light", + "doubleParameters": { + "intensity": 0.22 + }, + "stringParameters": { + "color": "255;255;255" + }, + "booleanParameters": {} + }, + { + "effectType": "Scene3D::DirectionalLight", + "name": "Sun", + "doubleParameters": { + "distanceFromCamera": 1500, + "elevation": 50, + "frustumSize": 3000, + "intensity": 1.4, + "minimumShadowBias": 0, + "rotation": 35 + }, + "stringParameters": { + "color": "255;246;224", + "shadowQuality": "high", + "top": "Z+" + }, + "booleanParameters": { + "isCastingShadow": true + } + } + ] + } + ], + "behaviorsSharedData": [] + }, + { + "b": 12, + "disableInputWhenNotFocused": true, + "mangledName": "Point_Lights", + "name": "Point Lights", + "r": 6, + "standardSortMethod": true, + "stopSoundsOnStartup": true, + "title": "", + "v": 7, + "uiSettings": { + "grid": false, + "gridType": "rectangular", + "gridWidth": 32, + "gridHeight": 32, + "gridOffsetX": 0, + "gridOffsetY": 0, + "gridColor": 10401023, + "gridAlpha": 0.8, + "snap": true, + "zoomFactor": 0.35, + "windowMask": false + }, + "objectsGroups": [], + "variables": [], + "instances": [ + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 20, + "height": 2400, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Ground", + "persistentUuid": "21d1f279-4719-1f6a-cbbb-722acfb1f6de", + "width": 2400, + "x": -1200, + "y": -1200, + "z": -20, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 460, + "height": 110, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Pillar", + "persistentUuid": "1e06c145-943f-f5a1-f990-12cdaa0825b5", + "width": 110, + "x": -55, + "y": -55, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 320, + "height": 60, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Backdrop", + "persistentUuid": "b5bb5390-66f6-b9c4-1e41-87e5df707d65", + "width": 900, + "x": -450, + "y": -900, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "1140e6b9-97f9-67c3-4213-3ec20f479dc8", + "width": 140, + "x": -520, + "y": -420, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "1feaa7a2-bd77-4fae-7133-7c976038df6c", + "width": 140, + "x": 380, + "y": -480, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "dd956ced-4997-5ff3-a7b8-1293e572377b", + "width": 140, + "x": -600, + "y": 320, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "97993a28-b8fc-b200-aa00-112a1d8816dd", + "width": 140, + "x": 460, + "y": 300, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "82992fdc-febb-527b-8ca2-32dd3bd57df4", + "width": 140, + "x": -80, + "y": -640, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "b675e5ea-db07-5902-72fe-4fd5f66e2190", + "width": 140, + "x": -60, + "y": 480, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "PointLightWarm", + "persistentUuid": "95051515-fb64-4ca5-6b63-80a275dc630a", + "width": 0, + "x": -500, + "y": -300, + "z": 180, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "PointLightCool", + "persistentUuid": "14004069-1b93-12bc-cfe0-9a63856a1578", + "width": 0, + "x": 480, + "y": -320, + "z": 180, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "PointLightMagenta", + "persistentUuid": "08a2515f-7cc8-93e4-7f3d-271a1e6a60e0", + "width": 0, + "x": -40, + "y": 420, + "z": 180, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + } + ], + "objects": [ + { + "assetStoreId": "", + "name": "Ground", + "persistentUuid": "e46f1434-2c55-2bca-2ccf-742ed8e26b67", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 2400, + "height": 2400, + "depth": 20, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "170;175;180", + "isCastingShadow": false, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "Crate", + "persistentUuid": "df5c6f4b-aedc-6655-8ef5-10c3d9b3294a", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 140, + "height": 140, + "depth": 140, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "196;146;92", + "isCastingShadow": true, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "Pillar", + "persistentUuid": "bcda4ad2-b8bf-a7ee-c150-3cb4ff8649d2", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 110, + "height": 110, + "depth": 460, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "205;208;212", + "isCastingShadow": true, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "Backdrop", + "persistentUuid": "405800cc-89d5-f501-5a8d-23977b035d4d", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 900, + "height": 60, + "depth": 320, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "150;154;162", + "isCastingShadow": true, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "PointLightWarm", + "persistentUuid": "c5016e19-f69f-1ed8-e1c8-ded2f9101305", + "type": "Light3D::PointLight3D", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "Color": "255;140;70", + "Intensity": 2.2, + "Decay": 2, + "IsCastingShadow": true, + "ShadowQuality": "Medium", + "ShadowCameraNearPlane": 20, + "ShadowCameraFarPlane": 2000, + "Range": 1400, + "ShadowBias": 0 + } + }, + { + "assetStoreId": "", + "name": "PointLightCool", + "persistentUuid": "8dc7336a-006c-23e0-f388-b946f5803983", + "type": "Light3D::PointLight3D", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "Color": "90;190;255", + "Intensity": 2.2, + "Decay": 2, + "IsCastingShadow": true, + "ShadowQuality": "Medium", + "ShadowCameraNearPlane": 20, + "ShadowCameraFarPlane": 2000, + "Range": 1400, + "ShadowBias": 0 + } + }, + { + "assetStoreId": "", + "name": "PointLightMagenta", + "persistentUuid": "e33287e0-e515-f368-29c2-c6fc3edb11c7", + "type": "Light3D::PointLight3D", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "Color": "255;100;200", + "Intensity": 2.2, + "Decay": 2, + "IsCastingShadow": true, + "ShadowQuality": "Medium", + "ShadowCameraNearPlane": 20, + "ShadowCameraFarPlane": 2000, + "Range": 1400, + "ShadowBias": 0 + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Ground" + }, + { + "objectName": "Crate" + }, + { + "objectName": "Pillar" + }, + { + "objectName": "Backdrop" + }, + { + "objectName": "PointLightWarm" + }, + { + "objectName": "PointLightCool" + }, + { + "objectName": "PointLightMagenta" + } + ] + }, + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "// Frame the props the same way in every scene and on every run, so the", + "// screenshots the gameplay tests take can be compared between versions.", + "if (!runtimeScene.__cameraPlaced) {", + " runtimeScene.__cameraPlaced = true;", + " gdjs.evtTools.camera.setCameraX(runtimeScene, 0, '', 0);", + " gdjs.evtTools.camera.setCameraY(runtimeScene, 1450, '', 0);", + " gdjs.scene3d.camera.setCameraZ(runtimeScene, 880, '', 0);", + " gdjs.scene3d.camera.setCameraRotationX(runtimeScene, 59, '', 0);", + " gdjs.scene3d.camera.setCameraRotationY(runtimeScene, 0, '', 0);", + "}" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "layers": [ + { + "ambientLightColorR": 14, + "ambientLightColorG": 16, + "ambientLightColorB": 24, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "", + "renderingType": "", + "visibility": true, + "cameras": [ + { + "defaultSize": true, + "defaultViewport": true, + "height": 0, + "viewportBottom": 1, + "viewportLeft": 0, + "viewportRight": 1, + "viewportTop": 0, + "width": 0 + } + ], + "effects": [ + { + "effectType": "Scene3D::AmbientLight", + "name": "Ambient light", + "doubleParameters": { + "intensity": 0.05 + }, + "stringParameters": { + "color": "255;255;255" + }, + "booleanParameters": {} + } + ] + } + ], + "behaviorsSharedData": [] + }, + { + "b": 12, + "disableInputWhenNotFocused": true, + "mangledName": "Spot_Lights", + "name": "Spot Lights", + "r": 6, + "standardSortMethod": true, + "stopSoundsOnStartup": true, + "title": "", + "v": 7, + "uiSettings": { + "grid": false, + "gridType": "rectangular", + "gridWidth": 32, + "gridHeight": 32, + "gridOffsetX": 0, + "gridOffsetY": 0, + "gridColor": 10401023, + "gridAlpha": 0.8, + "snap": true, + "zoomFactor": 0.35, + "windowMask": false + }, + "objectsGroups": [], + "variables": [], + "instances": [ + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 20, + "height": 2400, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Ground", + "persistentUuid": "ed514924-d2e4-5b2d-c862-19a99c1db74b", + "width": 2400, + "x": -1200, + "y": -1200, + "z": -20, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 460, + "height": 110, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Pillar", + "persistentUuid": "49a5c3e6-d6e6-bfb4-d8fe-6b193c5cef0c", + "width": 110, + "x": -55, + "y": -55, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 320, + "height": 60, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Backdrop", + "persistentUuid": "5e510294-7b95-b338-1670-2ceba2955432", + "width": 900, + "x": -450, + "y": -900, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "2b92439c-dea7-1970-fb7e-3227a8cae86c", + "width": 140, + "x": -520, + "y": -420, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "730511a8-9565-22bb-db96-51698cd16cda", + "width": 140, + "x": 380, + "y": -480, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "afa68705-e9c9-4f8f-b8ed-471122f3e33f", + "width": 140, + "x": -600, + "y": 320, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "88cc375e-a0fd-7e69-7764-ce5823d83558", + "width": 140, + "x": 460, + "y": 300, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "9aa9982a-7ab0-b8e1-86c1-740ec8926dcb", + "width": 140, + "x": -80, + "y": -640, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "2f0fccc2-50a8-95be-f958-80b02a9b87e0", + "width": 140, + "x": -60, + "y": 480, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 90, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "SpotLightWarm", + "persistentUuid": "2dab3063-cac1-5782-6165-e23ffc4a7530", + "width": 0, + "x": -450, + "y": -250, + "z": 620, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 90, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "SpotLightCool", + "persistentUuid": "04800480-b81c-1c1d-ce15-518cb3a1cc45", + "width": 0, + "x": 450, + "y": -250, + "z": 620, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + } + ], + "objects": [ + { + "assetStoreId": "", + "name": "Ground", + "persistentUuid": "e46f1434-2c55-2bca-2ccf-742ed8e26b67", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 2400, + "height": 2400, + "depth": 20, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "170;175;180", + "isCastingShadow": false, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "Crate", + "persistentUuid": "df5c6f4b-aedc-6655-8ef5-10c3d9b3294a", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 140, + "height": 140, + "depth": 140, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "196;146;92", + "isCastingShadow": true, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "Pillar", + "persistentUuid": "bcda4ad2-b8bf-a7ee-c150-3cb4ff8649d2", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 110, + "height": 110, + "depth": 460, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "205;208;212", + "isCastingShadow": true, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "Backdrop", + "persistentUuid": "405800cc-89d5-f501-5a8d-23977b035d4d", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 900, + "height": 60, + "depth": 320, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "150;154;162", + "isCastingShadow": true, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "SpotLightWarm", + "persistentUuid": "85ffde62-c943-b149-de4d-69dc43d73aee", + "type": "Light3D::SpotLight3D", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "Color": "255;236;180", + "ConeAngle": 34, + "Intensity": 14, + "Smoothing": 1, + "Decay": 2, + "Image": "", + "IsCastingShadow": true, + "ShadowQuality": "Medium", + "ShadowCameraNearPlane": 20, + "ShadowCameraFarPlane": 2000, + "ConeLength": 2000, + "ShadowBias": 0 + } + }, + { + "assetStoreId": "", + "name": "SpotLightCool", + "persistentUuid": "434cde1f-be0b-f340-da83-67b1cb0619aa", + "type": "Light3D::SpotLight3D", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "Color": "180;220;255", + "ConeAngle": 34, + "Intensity": 14, + "Smoothing": 1, + "Decay": 2, + "Image": "", + "IsCastingShadow": true, + "ShadowQuality": "Medium", + "ShadowCameraNearPlane": 20, + "ShadowCameraFarPlane": 2000, + "ConeLength": 2000, + "ShadowBias": 0 + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Ground" + }, + { + "objectName": "Crate" + }, + { + "objectName": "Pillar" + }, + { + "objectName": "Backdrop" + }, + { + "objectName": "SpotLightWarm" + }, + { + "objectName": "SpotLightCool" + } + ] + }, + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "// Frame the props the same way in every scene and on every run, so the", + "// screenshots the gameplay tests take can be compared between versions.", + "if (!runtimeScene.__cameraPlaced) {", + " runtimeScene.__cameraPlaced = true;", + " gdjs.evtTools.camera.setCameraX(runtimeScene, 0, '', 0);", + " gdjs.evtTools.camera.setCameraY(runtimeScene, 1450, '', 0);", + " gdjs.scene3d.camera.setCameraZ(runtimeScene, 880, '', 0);", + " gdjs.scene3d.camera.setCameraRotationX(runtimeScene, 59, '', 0);", + " gdjs.scene3d.camera.setCameraRotationY(runtimeScene, 0, '', 0);", + "}" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "layers": [ + { + "ambientLightColorR": 14, + "ambientLightColorG": 16, + "ambientLightColorB": 24, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "", + "renderingType": "", + "visibility": true, + "cameras": [ + { + "defaultSize": true, + "defaultViewport": true, + "height": 0, + "viewportBottom": 1, + "viewportLeft": 0, + "viewportRight": 1, + "viewportTop": 0, + "width": 0 + } + ], + "effects": [ + { + "effectType": "Scene3D::AmbientLight", + "name": "Ambient light", + "doubleParameters": { + "intensity": 0.05 + }, + "stringParameters": { + "color": "255;255;255" + }, + "booleanParameters": {} + } + ] + } + ], + "behaviorsSharedData": [] + }, + { + "b": 10, + "disableInputWhenNotFocused": true, + "mangledName": "Mixed_Lights", + "name": "Mixed Lights", + "r": 5, + "standardSortMethod": true, + "stopSoundsOnStartup": true, + "title": "", + "v": 6, + "uiSettings": { + "grid": false, + "gridType": "rectangular", + "gridWidth": 32, + "gridHeight": 32, + "gridOffsetX": 0, + "gridOffsetY": 0, + "gridColor": 10401023, + "gridAlpha": 0.8, + "snap": true, + "zoomFactor": 0.35, + "windowMask": false + }, + "objectsGroups": [], + "variables": [], + "instances": [ + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 20, + "height": 2400, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Ground", + "persistentUuid": "22dfa7b3-d332-db2e-6f60-a5f0c98ad1cf", + "width": 2400, + "x": -1200, + "y": -1200, + "z": -20, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 460, + "height": 110, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Pillar", + "persistentUuid": "e875554f-6f48-045f-77dd-e007ec681281", + "width": 110, + "x": -55, + "y": -55, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 320, + "height": 60, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Backdrop", + "persistentUuid": "fb74f53b-2e94-d59d-a8b4-b317842a75d8", + "width": 900, + "x": -450, + "y": -900, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "b67acebc-c8ac-e50f-c6f5-2017cd8d2107", + "width": 140, + "x": -520, + "y": -420, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "499db8ef-1794-f035-b870-0fbe178a8d40", + "width": 140, + "x": 380, + "y": -480, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "fc9913d1-5edb-39ee-d907-075d3f622cfe", + "width": 140, + "x": -600, + "y": 320, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "e08f7f62-9efd-2c0b-a0c2-9785ba5d2b37", + "width": 140, + "x": 460, + "y": 300, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "eec06225-61ec-4647-c12b-ae6b1f1b98a9", + "width": 140, + "x": -80, + "y": -640, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "d976a244-aadd-5742-bba9-d35ab2568465", + "width": 140, + "x": -60, + "y": 480, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedPoint", + "persistentUuid": "ab1970e9-5eb4-3852-b150-26d552a2d3f3", + "width": 0, + "x": 300, + "y": 0, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedPoint", + "persistentUuid": "049feb8a-a32e-1d93-a9f7-dc1a6965d462", + "width": 0, + "x": 478, + "y": 250, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedPoint", + "persistentUuid": "34214cda-67bc-c49b-4f68-11d1aae4bb51", + "width": 0, + "x": 443, + "y": 641, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedPoint", + "persistentUuid": "591288f4-88f2-350f-f301-f579e673a03c", + "width": 0, + "x": 122, + "y": 1012, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedPoint", + "persistentUuid": "94ff4de1-22c7-0196-d87b-71cc119aff4c", + "width": 0, + "x": -106, + "y": 280, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedPoint", + "persistentUuid": "e0e9e274-4cc1-3019-a049-267e669c7d64", + "width": 0, + "x": -404, + "y": 358, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedPoint", + "persistentUuid": "ebf66795-7cf2-bdf4-23d7-79400bba5e10", + "width": 0, + "x": -757, + "y": 186, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedPoint", + "persistentUuid": "9a702679-4bc8-5b8f-9e12-14726f321298", + "width": 0, + "x": -990, + "y": -244, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedPoint", + "persistentUuid": "244be702-6b6a-8a42-a284-f7164d8f8b9b", + "width": 0, + "x": -224, + "y": -198, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedPoint", + "persistentUuid": "1392a405-3592-c7ea-b7c2-55b538b9a0d7", + "width": 0, + "x": -191, + "y": -504, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedPoint", + "persistentUuid": "a980b446-1fc5-7c4a-85d7-8a2b01912fab", + "width": 0, + "x": 94, + "y": -774, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedPoint", + "persistentUuid": "23502fcf-1c47-165a-ec9b-f1060770a131", + "width": 0, + "x": 579, + "y": -839, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedPointShadow", + "persistentUuid": "ceb10a30-edd9-540c-5f36-0c6e30f249cf", + "width": 0, + "x": 265, + "y": -139, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedPointShadow", + "persistentUuid": "d1d1da37-9c09-a782-3b97-44dea2cb51d0", + "width": 0, + "x": 540, + "y": 0, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 90, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedSpot", + "persistentUuid": "d71e3361-7ee3-c6ac-efad-bd4053dbd4e5", + "width": 0, + "x": 690, + "y": 362, + "z": 560, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 90, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedSpot", + "persistentUuid": "9c35be70-c8e7-2aa3-2d9f-e980b98a31d5", + "width": 0, + "x": 579, + "y": 839, + "z": 560, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 90, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedSpot", + "persistentUuid": "b53c7850-2186-23f2-eaae-05abd0497c35", + "width": 0, + "x": 36, + "y": 297, + "z": 560, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 90, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedSpot", + "persistentUuid": "7d1e615d-ce68-8d3f-dfd9-7b6369a79d3c", + "width": 0, + "x": -191, + "y": 504, + "z": 560, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 90, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedSpot", + "persistentUuid": "421cb74f-3386-8ef1-9c65-d043d302e8cb", + "width": 0, + "x": -583, + "y": 517, + "z": 560, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 90, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedSpot", + "persistentUuid": "d29b0ff9-1509-feb8-e22a-578506534d01", + "width": 0, + "x": -990, + "y": 244, + "z": 560, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 90, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedSpot", + "persistentUuid": "e60591b7-6b99-e7f7-845d-cf586a028a6e", + "width": 0, + "x": -291, + "y": -71, + "z": 560, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 90, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedSpot", + "persistentUuid": "0d7a9528-5bac-d515-6028-070055d67a6b", + "width": 0, + "x": -404, + "y": -358, + "z": 560, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 90, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedSpot", + "persistentUuid": "cd93fb9c-82ec-8285-13a7-d9ecb08470d9", + "width": 0, + "x": -276, + "y": -729, + "z": 560, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 90, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedSpot", + "persistentUuid": "0856657d-867f-48c5-fd6b-a93e05a3c038", + "width": 0, + "x": 122, + "y": -1012, + "z": 560, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 90, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedSpotShadow", + "persistentUuid": "13bb79a9-9155-795c-1ac2-04512763cfe7", + "width": 0, + "x": 170, + "y": -246, + "z": 560, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 90, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "MixedSpotShadow", + "persistentUuid": "79357827-b406-c6e4-9c08-45e541722891", + "width": 0, + "x": 478, + "y": -250, + "z": 560, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + } + ], + "objects": [ + { + "assetStoreId": "", + "name": "Ground", + "persistentUuid": "e46f1434-2c55-2bca-2ccf-742ed8e26b67", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 2400, + "height": 2400, + "depth": 20, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "170;175;180", + "isCastingShadow": false, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "Crate", + "persistentUuid": "df5c6f4b-aedc-6655-8ef5-10c3d9b3294a", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 140, + "height": 140, + "depth": 140, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "196;146;92", + "isCastingShadow": true, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "Pillar", + "persistentUuid": "bcda4ad2-b8bf-a7ee-c150-3cb4ff8649d2", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 110, + "height": 110, + "depth": 460, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "205;208;212", + "isCastingShadow": true, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "Backdrop", + "persistentUuid": "405800cc-89d5-f501-5a8d-23977b035d4d", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 900, + "height": 60, + "depth": 320, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "150;154;162", + "isCastingShadow": true, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "MixedPoint", + "persistentUuid": "d9b5850c-4ba6-6924-bb12-3a71d641af26", + "type": "Light3D::PointLight3D", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "Color": "255;170;110", + "Intensity": 1.5, + "Decay": 2, + "IsCastingShadow": false, + "ShadowQuality": "Medium", + "ShadowCameraNearPlane": 20, + "ShadowCameraFarPlane": 2000, + "Range": 750, + "ShadowBias": 0 + } + }, + { + "assetStoreId": "", + "name": "MixedPointShadow", + "persistentUuid": "3f5d7912-6537-ef1f-fe3d-b050d6dbd394", + "type": "Light3D::PointLight3D", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "Color": "255;210;150", + "Intensity": 1.6, + "Decay": 2, + "IsCastingShadow": true, + "ShadowQuality": "Medium", + "ShadowCameraNearPlane": 20, + "ShadowCameraFarPlane": 2000, + "Range": 800, + "ShadowBias": 0 + } + }, + { + "assetStoreId": "", + "name": "MixedSpot", + "persistentUuid": "a13deb4c-0901-17be-ca1a-d875b1e16807", + "type": "Light3D::SpotLight3D", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "Color": "150;205;255", + "ConeAngle": 40, + "Intensity": 5, + "Smoothing": 1, + "Decay": 2, + "Image": "", + "IsCastingShadow": false, + "ShadowQuality": "Medium", + "ShadowCameraNearPlane": 20, + "ShadowCameraFarPlane": 2000, + "ConeLength": 2000, + "ShadowBias": 0 + } + }, + { + "assetStoreId": "", + "name": "MixedSpotShadow", + "persistentUuid": "6697f33c-05c5-ea0e-56ea-dd7b9637f87b", + "type": "Light3D::SpotLight3D", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "Color": "190;225;255", + "ConeAngle": 40, + "Intensity": 5, + "Smoothing": 1, + "Decay": 2, + "Image": "", + "IsCastingShadow": true, + "ShadowQuality": "Medium", + "ShadowCameraNearPlane": 20, + "ShadowCameraFarPlane": 2000, + "ConeLength": 2000, + "ShadowBias": 0 + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Ground" + }, + { + "objectName": "Crate" + }, + { + "objectName": "Pillar" + }, + { + "objectName": "Backdrop" + }, + { + "objectName": "MixedPoint" + }, + { + "objectName": "MixedPointShadow" + }, + { + "objectName": "MixedSpot" + }, + { + "objectName": "MixedSpotShadow" + } + ] + }, + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "// Frame the props the same way in every scene and on every run, so the", + "// screenshots the gameplay tests take can be compared between versions.", + "if (!runtimeScene.__cameraPlaced) {", + " runtimeScene.__cameraPlaced = true;", + " gdjs.evtTools.camera.setCameraX(runtimeScene, 0, '', 0);", + " gdjs.evtTools.camera.setCameraY(runtimeScene, 1450, '', 0);", + " gdjs.scene3d.camera.setCameraZ(runtimeScene, 880, '', 0);", + " gdjs.scene3d.camera.setCameraRotationX(runtimeScene, 59, '', 0);", + " gdjs.scene3d.camera.setCameraRotationY(runtimeScene, 0, '', 0);", + "}" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "layers": [ + { + "ambientLightColorR": 12, + "ambientLightColorG": 14, + "ambientLightColorB": 20, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "", + "renderingType": "", + "visibility": true, + "cameras": [ + { + "defaultSize": true, + "defaultViewport": true, + "height": 0, + "viewportBottom": 1, + "viewportLeft": 0, + "viewportRight": 1, + "viewportTop": 0, + "width": 0 + } + ], + "effects": [ + { + "effectType": "Scene3D::AmbientLight", + "name": "Ambient light", + "doubleParameters": { + "intensity": 0.05 + }, + "stringParameters": { + "color": "255;255;255" + }, + "booleanParameters": {} + } + ] + } + ], + "behaviorsSharedData": [] + }, + { + "b": 10, + "disableInputWhenNotFocused": true, + "mangledName": "Crowded_Point_Lights", + "name": "Crowded Point Lights", + "r": 5, + "standardSortMethod": true, + "stopSoundsOnStartup": true, + "title": "", + "v": 6, + "uiSettings": { + "grid": false, + "gridType": "rectangular", + "gridWidth": 32, + "gridHeight": 32, + "gridOffsetX": 0, + "gridOffsetY": 0, + "gridColor": 10401023, + "gridAlpha": 0.8, + "snap": true, + "zoomFactor": 0.35, + "windowMask": false + }, + "objectsGroups": [], + "variables": [], + "instances": [ + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 20, + "height": 2400, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Ground", + "persistentUuid": "22dfa7b3-d332-db2e-6f60-a5f0c98ad1cf", + "width": 2400, + "x": -1200, + "y": -1200, + "z": -20, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 460, + "height": 110, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Pillar", + "persistentUuid": "e875554f-6f48-045f-77dd-e007ec681281", + "width": 110, + "x": -55, + "y": -55, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 320, + "height": 60, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Backdrop", + "persistentUuid": "fb74f53b-2e94-d59d-a8b4-b317842a75d8", + "width": 900, + "x": -450, + "y": -900, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "b67acebc-c8ac-e50f-c6f5-2017cd8d2107", + "width": 140, + "x": -520, + "y": -420, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "499db8ef-1794-f035-b870-0fbe178a8d40", + "width": 140, + "x": 380, + "y": -480, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "fc9913d1-5edb-39ee-d907-075d3f622cfe", + "width": 140, + "x": -600, + "y": 320, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "e08f7f62-9efd-2c0b-a0c2-9785ba5d2b37", + "width": 140, + "x": 460, + "y": 300, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "eec06225-61ec-4647-c12b-ae6b1f1b98a9", + "width": 140, + "x": -80, + "y": -640, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": true, + "depth": 140, + "height": 140, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "Crate", + "persistentUuid": "d976a244-aadd-5742-bba9-d35ab2568465", + "width": 140, + "x": -60, + "y": 480, + "z": 0, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "CrowdedPointShadow", + "persistentUuid": "41a578a3-0e8e-4af5-81ce-2810d7c55432", + "width": 0, + "x": 620, + "y": 0, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "CrowdedPointShadow", + "persistentUuid": "08c119c4-8fc7-4232-a70c-d9c43181f2c1", + "width": 0, + "x": 438, + "y": 438, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "CrowdedPointShadow", + "persistentUuid": "aceb6eb8-0c1c-473b-bfdf-cdffdccfd9cd", + "width": 0, + "x": 0, + "y": 620, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "CrowdedPointShadow", + "persistentUuid": "ee7abeab-387e-4761-a427-b7e05e50442a", + "width": 0, + "x": -438, + "y": 438, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "CrowdedPointShadow", + "persistentUuid": "d4e10e44-ae1d-4eae-a1a6-102eebd60e48", + "width": 0, + "x": -620, + "y": 0, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "CrowdedPointShadow", + "persistentUuid": "d6e2e318-0c7f-4425-bf35-48704f62f167", + "width": 0, + "x": -438, + "y": -438, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "CrowdedPointShadow", + "persistentUuid": "dbbe65db-8b5b-45ac-8faa-9ed8109abb84", + "width": 0, + "x": 0, + "y": -620, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + }, + { + "angle": 0, + "rotationX": 0, + "rotationY": 0, + "customSize": false, + "depth": 0, + "height": 0, + "keepRatio": true, + "layer": "", + "locked": false, + "name": "CrowdedPointShadow", + "persistentUuid": "cdfc7464-a19f-495f-ae6b-e6a3b404784d", + "width": 0, + "x": 438, + "y": -438, + "z": 150, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + } + ], + "objects": [ + { + "assetStoreId": "", + "name": "Ground", + "persistentUuid": "e46f1434-2c55-2bca-2ccf-742ed8e26b67", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 2400, + "height": 2400, + "depth": 20, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "170;175;180", + "isCastingShadow": false, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "Crate", + "persistentUuid": "df5c6f4b-aedc-6655-8ef5-10c3d9b3294a", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 140, + "height": 140, + "depth": 140, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "196;146;92", + "isCastingShadow": true, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "Pillar", + "persistentUuid": "bcda4ad2-b8bf-a7ee-c150-3cb4ff8649d2", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 110, + "height": 110, + "depth": 460, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "205;208;212", + "isCastingShadow": true, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "Backdrop", + "persistentUuid": "405800cc-89d5-f501-5a8d-23977b035d4d", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 900, + "height": 60, + "depth": 320, + "enableTextureTransparency": false, + "facesOrientation": "Y", + "backFaceUpThroughWhichAxisRotation": "X", + "materialType": "StandardWithoutMetalness", + "tint": "150;154;162", + "isCastingShadow": true, + "isReceivingShadow": true, + "frontFaceResourceName": "assets/LightPlaygroundSurface.png", + "frontFaceVisible": true, + "frontFaceResourceRepeat": true, + "backFaceResourceName": "assets/LightPlaygroundSurface.png", + "backFaceVisible": true, + "backFaceResourceRepeat": true, + "leftFaceResourceName": "assets/LightPlaygroundSurface.png", + "leftFaceVisible": true, + "leftFaceResourceRepeat": true, + "rightFaceResourceName": "assets/LightPlaygroundSurface.png", + "rightFaceVisible": true, + "rightFaceResourceRepeat": true, + "topFaceResourceName": "assets/LightPlaygroundSurface.png", + "topFaceVisible": true, + "topFaceResourceRepeat": true, + "bottomFaceResourceName": "assets/LightPlaygroundSurface.png", + "bottomFaceVisible": true, + "bottomFaceResourceRepeat": true + } + }, + { + "assetStoreId": "", + "name": "CrowdedPointShadow", + "persistentUuid": "c4164626-0bc3-4ec5-8e5d-33fdab7d9bcd", + "type": "Light3D::PointLight3D", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "Color": "255;205;150", + "Intensity": 1.8, + "Decay": 2, + "IsCastingShadow": true, + "ShadowQuality": "Medium", + "ShadowCameraNearPlane": 20, + "ShadowCameraFarPlane": 2000, + "Range": 900, + "ShadowBias": 0 + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Ground" + }, + { + "objectName": "Crate" + }, + { + "objectName": "Pillar" + }, + { + "objectName": "Backdrop" + }, + { + "objectName": "CrowdedPointShadow" + } + ] + }, + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "// Frame the props the same way in every scene and on every run, so the", + "// screenshots the gameplay tests take can be compared between versions.", + "if (!runtimeScene.__cameraPlaced) {", + " runtimeScene.__cameraPlaced = true;", + " gdjs.evtTools.camera.setCameraX(runtimeScene, 0, '', 0);", + " gdjs.evtTools.camera.setCameraY(runtimeScene, 1450, '', 0);", + " gdjs.scene3d.camera.setCameraZ(runtimeScene, 880, '', 0);", + " gdjs.scene3d.camera.setCameraRotationX(runtimeScene, 59, '', 0);", + " gdjs.scene3d.camera.setCameraRotationY(runtimeScene, 0, '', 0);", + "}" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "layers": [ + { + "ambientLightColorR": 12, + "ambientLightColorG": 14, + "ambientLightColorB": 20, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "", + "renderingType": "", + "visibility": true, + "cameras": [ + { + "defaultSize": true, + "defaultViewport": true, + "height": 0, + "viewportBottom": 1, + "viewportLeft": 0, + "viewportRight": 1, + "viewportTop": 0, + "width": 0 + } + ], + "effects": [ + { + "effectType": "Scene3D::AmbientLight", + "name": "Ambient light", + "doubleParameters": { + "intensity": 0.05 + }, + "stringParameters": { + "color": "255;255;255" + }, + "booleanParameters": {} + } + ] + } + ], + "behaviorsSharedData": [] + } + ], + "externalEvents": [], + "externalLayouts": [], + "eventsFunctionsExtensions": [ + { + "author": "", + "category": "Visual effect", + "dimension": "3D", + "extensionNamespace": "", + "fullName": "3D lights", + "gdevelopVersion": ">=5.5.222", + "helpPath": "/objects/3d-light", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0ibWRpLWxpZ2h0YnVsYi1vbi1vdXRsaW5lIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTIwLDExSDIzVjEzSDIwVjExTTEsMTFINFYxM0gxVjExTTEzLDFWNEgxMVYxSDEzTTQuOTIsMy41TDcuMDUsNS42NEw1LjYzLDcuMDVMMy41LDQuOTNMNC45MiwzLjVNMTYuOTUsNS42M0wxOS4wNywzLjVMMjAuNSw0LjkzTDE4LjM3LDcuMDVMMTYuOTUsNS42M00xMiw2QTYsNiAwIDAsMSAxOCwxMkMxOCwxNC4yMiAxNi43OSwxNi4xNiAxNSwxNy4yVjE5QTEsMSAwIDAsMSAxNCwyMEgxMEExLDEgMCAwLDEgOSwxOVYxNy4yQzcuMjEsMTYuMTYgNiwxNC4yMiA2LDEyQTYsNiAwIDAsMSAxMiw2TTE0LDIxVjIyQTEsMSAwIDAsMSAxMywyM0gxMUExLDEgMCAwLDEgMTAsMjJWMjFIMTRNMTEsMThIMTNWMTUuODdDMTQuNzMsMTUuNDMgMTYsMTMuODYgMTYsMTJBNCw0IDAgMCwwIDEyLDhBNCw0IDAgMCwwIDgsMTJDOCwxMy44NiA5LjI3LDE1LjQzIDExLDE1Ljg3VjE4WiIgLz48L3N2Zz4=", + "name": "Light3D", + "previewIconUrl": "https://asset-resources.gdevelop.io/public-resources/Icons/f237ae4e3b857c556846c7b2c0b132556fd4bcdeff217034b4d9c97dc1aab1d6_lightbulb-on-outline.svg", + "shortDescription": "A collection of light object for 3D.", + "version": "1.0.3", + "description": "A collection of light object for 3D.", + "origin": { + "identifier": "Light3D", + "name": "gdevelop-extension-store" + }, + "tags": [ + "3d", + "light" + ], + "authorIds": [ + "IWykYNRvhCZBN3vEgKEbBPOR3Oc2" + ], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [], + "eventsFunctions": [ + { + "description": "Define spot light helper classes JavaScript code.", + "fullName": "Define spot light helper classes", + "functionType": "Action", + "name": "DefineSpotLightHelperClasses", + "private": true, + "sentence": "Define spot light helper classes JavaScript code", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "//@ts-ignore", + "if (gdjs.__light3DExtension.spot) {", + " //@ts-ignore", + " return;", + "}", + "", + "/**", + " * @typedef {gdjs.CustomRuntimeObject3D & {__light3D: THREE.SpotLight, _getIsCastingShadow: () => boolean, _getConeAngle: () => number, _getColor: () => string}} SpotLightRuntimeObject", + " */", + "", + "const game = runtimeScene.getGame();", + "", + "const coneLength = 64;", + "", + "class SpotLightHelper extends THREE.Object3D {", + " /** @type {SpotLightRuntimeObject} */", + " object;", + " /** @type {THREE.LineSegments} */", + " cone;", + " /** @type {THREE.LineSegments} */", + " centerLine;", + " /** @type {THREE.Mesh} */", + " originBox;", + "", + "\t/**", + " * @param {SpotLightRuntimeObject} object", + "\t */", + " constructor(object) {", + " super();", + " this.object = object;", + " this.type = 'SpotLightHelper';", + "", + " const coneGeometry = new THREE.BufferGeometry();", + " const conePositions = [", + " 0, 0, 0, 1, 0, 0,", + " 0, 0, 0, 1, 1, 0,", + " 0, 0, 0, 1, - 1, 0,", + " 0, 0, 0, 1, 0, 1,", + " 0, 0, 0, 1, 0, - 1", + " ];", + " for (let i = 0, j = 1, l = 32; i < l; i++ , j++) {", + " const p1 = (i / l) * Math.PI * 2;", + " const p2 = (j / l) * Math.PI * 2;", + " conePositions.push(", + " 1, Math.cos(p1), Math.sin(p1),", + " 1, Math.cos(p2), Math.sin(p2)", + " );", + " }", + " coneGeometry.setAttribute('position', new THREE.Float32BufferAttribute(conePositions, 3));", + " this.cone = new THREE.LineSegments(", + " coneGeometry,", + " new THREE.LineBasicMaterial({ fog: false, toneMapped: false })", + " );", + " this.add(this.cone);", + " const centerLineGeometry = new THREE.BufferGeometry();", + " centerLineGeometry.setAttribute('position', new THREE.Float32BufferAttribute([", + " 0, 0, 0, coneLength, 0, 0", + " ], 3));", + " this.centerLine = new THREE.LineSegments(", + " centerLineGeometry,", + " new THREE.LineBasicMaterial({ fog: false, toneMapped: false })", + " );", + " this.add(this.centerLine);", + "", + " this.originBox = new THREE.Mesh(", + " new THREE.BoxGeometry(16, 16, 16),", + " new THREE.MeshBasicMaterial({ fog: false, toneMapped: false })", + " );", + " this.add(this.originBox);", + " this.update();", + "", + " //@ts-ignore", + " this.originBox.gdjsRuntimeObject = object;", + " }", + "", + " dispose() {", + " this.cone.geometry.dispose();", + " this.cone.material.dispose();", + " this.centerLine.geometry.dispose();", + " this.centerLine.material.dispose();", + " this.originBox.geometry.dispose();", + " this.originBox.material.dispose();", + " }", + "", + " update() {", + " /** @type {number} */", + " const coneAngle = gdjs.toRad(this.object._getConeAngle());", + " const coneWidth = coneLength * Math.sin(coneAngle);", + " const coneHeight = coneLength * Math.cos(coneAngle);", + " this.cone.scale.set(coneHeight, coneWidth, coneWidth);", + " const color = gdjs.rgbOrHexStringToNumber(this.object._getColor());", + " this.cone.material.color.set(color);", + " this.centerLine.material.color.set(color);", + " this.originBox.material.color.set(color);", + " }", + "}", + "", + "/**", + " * @param {string} colorString", + " * @param {THREE.Color} threeColor", + " */", + "const setThreeColor = (colorString, threeColor) => {", + " const integerColor = gdjs.rgbOrHexToRGBColor(colorString);", + " threeColor.r = integerColor[0] / 255;", + " threeColor.g = integerColor[1] / 255;", + " threeColor.b = integerColor[2] / 255;", + "};", + "", + "class SpotLightAdapter {", + " /**", + " * @param object {gdjs.CustomRuntimeObject3D}", + " * @param spotLight {THREE.SpotLight}", + " */", + " constructor(object, spotLight) {", + " this.object = object;", + " this.spotLight = spotLight;", + " }", + "", + " /**", + " * @param targetX {number}", + " * @param targetY {number}", + " * @param targetZ {number}", + " */", + " lookAtPosition(targetX, targetY, targetZ) {", + " const runtimeSene = this.object.getRuntimeScene();", + " const inverseWorldScale = runtimeSene.getRenderer3DInverseWorldScale ? runtimeSene.getRenderer3DInverseWorldScale() : 1;", + "", + " // Remove from the parent to avoid the scene scale of -1 on Y to mess with the formula.", + " const parent = this.spotLight.parent;", + " this.spotLight.parent = null;", + " this.spotLight.lookAt(", + " targetX * inverseWorldScale,", + " targetY * inverseWorldScale,", + " targetZ * inverseWorldScale);", + " this.spotLight.parent = parent;", + "", + " // Angle setters update Three.js angles, so we save them first.", + " const rotationX = gdjs.toDegrees(this.spotLight.rotation.x);", + " const rotationY = gdjs.toDegrees(this.spotLight.rotation.y);", + " const rotationZ = gdjs.toDegrees(this.spotLight.rotation.z);", + " this.object.setRotationX(rotationX);", + " this.object.setRotationY(rotationY);", + " this.object.setAngle(rotationZ + 90);", + " }", + "", + " /**", + " * @param color {string}", + " */", + " setColor(color) {", + " setThreeColor(color, this.spotLight.color);", + " }", + "", + " /**", + " * @param intensity {number}", + " */", + " setIntensity(intensity) {", + " this.spotLight.intensity = intensity;", + " }", + "", + " /**", + " * @param decay {number}", + " */", + " setDecay(decay) {", + " this.spotLight.decay = decay;", + " }", + "", + " /**", + " * @param value {number}", + " */", + " setConeLength(value) {", + " const runtimeSene = this.object.getRuntimeScene();", + " const inverseWorldScale = runtimeSene.getRenderer3DInverseWorldScale ? runtimeSene.getRenderer3DInverseWorldScale() : 1;", + " this.spotLight.distance = value * inverseWorldScale;", + " }", + "", + " /**", + " * @param coneAngle {number}", + " */", + " setConeAngle(coneAngle) {", + " this.spotLight.angle = coneAngle * Math.PI / 180;", + " }", + "", + " /**", + " * @param smoothing {number}", + " */", + " setSmoothing(smoothing) {", + " this.spotLight.penumbra = smoothing;", + " }", + "", + " /**", + " * @param isCastingShadow {boolean}", + " */", + " setCastingShadow(isCastingShadow) {", + " // This is applied by applyVisibilityAndShadow", + " }", + "", + " /**", + " * @param shadowQuality {\"Low\" | \"Medium\" | \"High\" | \"VeryHigh\"}", + " */", + " setShadowQuality(shadowQuality) {", + " let size = 512;", + " switch (shadowQuality) {", + " case \"Low\":", + " size = 256;", + " break;", + " case \"Medium\":", + " size = 512;", + " break;", + " case \"High\":", + " size = 1024;", + " break;", + " case \"VeryHigh\":", + " size = 2048;", + " break;", + " }", + " const shadow = this.spotLight.shadow;", + " const mapSize = shadow.mapSize;", + " if (mapSize.width !== size) {", + " mapSize.set(size, size);", + "", + " // Force the recreation of the shadow map texture:", + " if (shadow.map) {", + " shadow.map.dispose();", + " shadow.map = null;", + " }", + " shadow.needsUpdate = true;", + " }", + " }", + "", + " /**", + " * @param value {number}", + " */", + " setShadowCameraNearPlane(value) {", + " const runtimeSene = this.object.getRuntimeScene();", + " const inverseWorldScale = runtimeSene.getRenderer3DInverseWorldScale ? runtimeSene.getRenderer3DInverseWorldScale() : 1;", + " this.spotLight.shadow.camera.near = value * inverseWorldScale;", + " }", + "", + " /**", + " * @param value {number}", + " */", + " setShadowCameraFarPlane(value) {", + " const runtimeSene = this.object.getRuntimeScene();", + " const inverseWorldScale = runtimeSene.getRenderer3DInverseWorldScale ? runtimeSene.getRenderer3DInverseWorldScale() : 1;", + " this.spotLight.shadow.camera.far = value * inverseWorldScale;", + " }", + "", + " /**", + " * @param value {number}", + " * @param quality {\"Low\" | \"Medium\" | \"High\" | \"VeryHigh\"}", + " * @param coneAngle {number}", + " */", + " setShadowBias(value, quality, coneAngle) {", + " const runtimeSene = this.object.getRuntimeScene();", + " const inverseWorldScale = runtimeSene.getRenderer3DInverseWorldScale ? runtimeSene.getRenderer3DInverseWorldScale() : 1;", + " const biasMultiplier =", + " quality === 'Low'", + " ? 8", + " : quality === 'Medium'", + " ? 4", + " : quality === 'High'", + " ? 2 : 1;", + " // Multiply by 0.125 to make values around 0.001 work best.", + " this.spotLight.shadow.bias = -value * 0.125 * biasMultiplier *", + " Math.tan(gdjs.toRad(gdjs.evtTools.common.clamp(coneAngle, 0, 89))) *", + " inverseWorldScale;", + " }", + "", + " /**", + " * @param resourceName {string}", + " */", + " setImage(resourceName) {", + " if (!resourceName) {", + " this.spotLight.map = null;", + " return;", + " }", + " const texture = game.getImageManager().getThreeTexture(resourceName);", + " this.spotLight.map = texture;", + " }", + "}", + "", + "//@ts-ignore", + "gdjs.__light3DExtension.spot = {", + " SpotLightAdapter,", + " SpotLightHelper,", + "}" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "Define point light helper classes JavaScript code.", + "fullName": "Define point light helper classes", + "functionType": "Action", + "name": "DefinePointLightHelperClasses", + "private": true, + "sentence": "Define point light helper classes JavaScript code", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "//@ts-ignore", + "if (gdjs.__light3DExtension.point) {", + " //@ts-ignore", + " return;", + "}", + "", + "/**", + " * @typedef {gdjs.CustomRuntimeObject3D & {__light3D: THREE.PointLight, _getIsCastingShadow: () => boolean, _getColor: () => string}} PointLightRuntimeObject", + " */", + "", + "const game = runtimeScene.getGame();", + "", + "/**", + " * @extends {THREE.Mesh}", + " */", + "class PointLightHelper extends THREE.Mesh {", + " /** @type {PointLightRuntimeObject} */", + " object;", + "", + "\t/**", + " * @param {PointLightRuntimeObject} object", + "\t */", + " constructor(object) {", + " const geometry = new THREE.SphereGeometry(16, 4, 2);", + " const material = new THREE.MeshBasicMaterial({ wireframe: true, fog: false, toneMapped: false });", + " super(geometry, material);", + " this.object = object;", + " this.update();", + "", + " //@ts-ignore", + " this.gdjsRuntimeObject = object;", + " }", + "", + " dispose() {", + " this.geometry.dispose();", + " this.material.dispose();", + " }", + "", + " update() {", + " const color = gdjs.rgbOrHexStringToNumber(this.object._getColor());", + " this.material.color.set(color);", + " }", + "}", + "", + "/**", + " * @param {string} colorString", + " * @param {THREE.Color} threeColor", + " */", + "const setThreeColor = (colorString, threeColor) => {", + " const integerColor = gdjs.rgbOrHexToRGBColor(colorString);", + " threeColor.r = integerColor[0] / 255;", + " threeColor.g = integerColor[1] / 255;", + " threeColor.b = integerColor[2] / 255;", + "};", + "", + "class PointLightAdapter {", + " /**", + " * @param object {gdjs.CustomRuntimeObject3D}", + " * @param pointLight {THREE.PointLight}", + " */", + " constructor(object, pointLight) {", + " this.object = object;", + " this.pointLight = pointLight;", + " }", + "", + " /**", + " * @param color {string}", + " */", + " setColor(color) {", + " setThreeColor(color, this.pointLight.color);", + " }", + "", + " /**", + " * @param intensity {number}", + " */", + " setIntensity(intensity) {", + " this.pointLight.intensity = intensity;", + " }", + "", + " /**", + " * @param decay {number}", + " */", + " setDecay(decay) {", + " this.pointLight.decay = decay;", + " }", + "", + " /**", + " * @param value {number}", + " */", + " setRange(value) {", + " this.pointLight.distance = value;", + " }", + "", + " /**", + " * @param isCastingShadow {boolean}", + " */", + " setCastingShadow(isCastingShadow) {", + " // This is applied by applyVisibilityAndShadow", + " }", + "", + " /**", + " * @param shadowQuality {\"Low\" | \"Medium\" | \"High\"}", + " */", + " setShadowQuality(shadowQuality) {", + " let size = 512;", + " switch (shadowQuality) {", + " case \"Low\":", + " size = 512;", + " break;", + " case \"Medium\":", + " size = 1024;", + " break;", + " case \"High\":", + " size = 2048;", + " break;", + " }", + " const shadow = this.pointLight.shadow;", + " const mapSize = shadow.mapSize;", + " if (mapSize.width !== size) {", + " mapSize.set(size, size);", + "", + " // Force the recreation of the shadow map texture:", + " if (shadow.map) {", + " shadow.map.dispose();", + " shadow.map = null;", + " }", + " shadow.needsUpdate = true;", + " }", + " }", + "", + " /**", + " * @param value {number}", + " */", + " setShadowCameraNearPlane(value) {", + " const runtimeSene = this.object.getRuntimeScene();", + " const inverseWorldScale = runtimeSene.getRenderer3DInverseWorldScale ? runtimeSene.getRenderer3DInverseWorldScale() : 1;", + "", + " this.pointLight.shadow.camera.near = value * inverseWorldScale;", + " }", + "", + " /**", + " * @param value {number}", + " */", + " setShadowCameraFarPlane(value) {", + " const runtimeSene = this.object.getRuntimeScene();", + " const inverseWorldScale = runtimeSene.getRenderer3DInverseWorldScale ? runtimeSene.getRenderer3DInverseWorldScale() : 1;", + "", + " this.pointLight.shadow.camera.far = value * inverseWorldScale;", + " }", + "", + " /**", + " * @param value {number}", + " * @param quality {\"Low\" | \"Medium\" | \"High\"}", + " */", + " setShadowBias(value, quality) {", + " const runtimeSene = this.object.getRuntimeScene();", + " const inverseWorldScale = runtimeSene.getRenderer3DInverseWorldScale ? runtimeSene.getRenderer3DInverseWorldScale() : 1;", + "", + " const biasMultiplier =", + " quality === 'Low'", + " ? 4", + " : quality === 'Medium'", + " ? 2", + " : 1;", + " this.pointLight.shadow.bias = -value * biasMultiplier * inverseWorldScale;", + " }", + "}", + "", + "//@ts-ignore", + "gdjs.__light3DExtension.point = {", + " PointLightAdapter,", + " PointLightHelper,", + "}" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "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": [ + "//@ts-ignore", + "if (gdjs.__light3DExtension) {", + " //@ts-ignore", + " return;", + "}", + "", + "/**", + " * @typedef {gdjs.CustomRuntimeObject3D & {__light3D: THREE.SpotLight | THREE.PointLight, _getIsCastingShadow: () => boolean}} LightRuntimeObject", + " */", + "", + "const game = runtimeScene.getGame();", + "const isInGameEdition = game.isInGameEdition && game.isInGameEdition();", + "const logger = new gdjs.Logger('3D lights');", + "", + "", + "class Light3DRenderer extends gdjs.CustomRuntimeObject3DRenderer {", + "", + " constructor(", + " object,", + " instanceContainer,", + " parent", + " ) {", + " super(object, instanceContainer, parent);", + " }", + "", + " _updateThreeGroup() {", + " /** @type {LightRuntimeObject} */", + " //@ts-ignore", + " const object = this._object;", + " const threeObject3D = this.get3DRendererObject();", + "", + " threeObject3D.rotation.set(", + " gdjs.toRad(object.getRotationX()),", + " gdjs.toRad(object.getRotationY()),", + " gdjs.toRad(object.angle)", + " );", + "", + " threeObject3D.position.set(", + " object.getX(),", + " object.getY(),", + " object.getZ()", + " );", + "", + " // Force the scale to 1 because the light doesn't really has a size.", + " threeObject3D.scale.set(", + " object.isFlippedX() ? -1 : 1,", + " object.isFlippedY() ? -1 : 1,", + " object.isFlippedZ() ? -1 : 1", + " );", + "", + " threeObject3D.visible = !this._object.hidden;", + "", + " const spotLight = object.__light3D;", + "", + " const editor = game.getInGameEditor ? game.getInGameEditor() : null;", + "", + " spotLight.castShadow = false;", + " spotLight.visible = false;", + "", + " if (!object.isHidden()) {", + " let isSelected = false;", + " if (editor) {", + " const selectedObject = editor._selection.getLastSelectedObject();", + " let parentObject = object;", + " isSelected = parentObject === selectedObject;", + " while (!isSelected && parentObject.getInstanceContainer()", + " //@ts-ignore", + " .getOwner) {", + " parentObject = parentObject.getInstanceContainer()", + " //@ts-ignore", + " .getOwner();", + " isSelected = parentObject === selectedObject;", + " }", + " }", + " if (!editor || !editor.areEffectsHidden() || isSelected) {", + " let rootObject = object;", + " while (rootObject.getInstanceContainer()", + " //@ts-ignore", + " .getOwner) {", + " rootObject = rootObject.getInstanceContainer()", + " //@ts-ignore", + " .getOwner();", + " }", + " const runtimeScene = rootObject.getRuntimeScene();", + " let distanceSq = 0;", + " if (!isSelected) {", + " const layerName = rootObject.getLayer();", + " const cameraX = gdjs.evtTools.camera.getCameraX(runtimeScene, layerName, 0);", + " const cameraY = gdjs.evtTools.camera.getCameraY(runtimeScene, layerName, 0);", + " const cameraZ = gdjs.scene3d.camera.getCameraZ(runtimeScene, layerName, 0);", + " const deltaX = rootObject.getX() - cameraX;", + " const deltaY = rootObject.getY() - cameraY;", + " const deltaZ = rootObject.getZ() - cameraZ;", + " distanceSq = deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ;", + " }", + " getLightManager(", + " //@ts-ignore", + " runtimeScene", + " ).applyVisibilityAndShadow(object, distanceSq);", + " }", + " }", + "", + " // Force the visibility to be checked every frame", + " this._isContainerDirty = true;", + " }", + "}", + "", + "const editorLightCountMax = {", + " value: 20", + "};", + "", + "const lightCountMax = {", + " value: 20", + "};", + "", + "const editorLightShadowCountMax = {", + " value: 4", + "};", + "", + "const lightShadowCountMax = {", + " value: 4", + "};", + "", + "gdjs.registerRuntimeScenePreEventsCallback(", + " runtimeScene => {", + " getLightManager(", + " //@ts-ignore", + " runtimeScene.getScene()", + " ).clear();", + " });", + "if (gdjs.registerInGameEditorPostStepCallback) {", + " gdjs.registerInGameEditorPostStepCallback(", + " inGameEditor => {", + " getLightManager(", + " //@ts-ignore", + " inGameEditor.getEditedInstanceContainer().getScene()", + " ).clear();", + " });", + "}", + "", + "/**", + " * How many lights of each kind this device can take.", + " *", + " * These are hard limits rather than performance trade-offs. three.js binds one", + " * texture unit per shadow map and one more for a spot light's projected", + " * texture, and spends a varying on every shadow casting light. Going over what", + " * the driver allows does not make the scene slower - the shader fails to link", + " * and everything using that material renders black. Only 16 fragment texture", + " * units and 15 varyings are guaranteed across devices, and materials need most", + " * of those, so the budget is read from the device instead of being fixed.", + " *", + " * The budget is shared between the light kinds a scene uses, so it is given", + " * how many of them there are rather than assuming all of them: a scene lit by", + " * point lights alone would otherwise have three quarters of its texture units", + " * held back for kinds that never show up.", + " *", + " * @param {THREE.WebGLRenderer | null} threeRenderer", + " * @param {number} kindCount How many light kinds the scene uses, at least one.", + " * @returns {{shadowCount: number, mapCount: number, count: number}}", + " */", + "function computeDeviceLightBudget(threeRenderer, kindCount) {", + " // When the renderer cannot be reached, assume the guaranteed minimums", + " // rather than the device this happens to be running on.", + " const capabilities = (threeRenderer && threeRenderer.capabilities) || {};", + " const maxTextures = capabilities.maxTextures || 16;", + " const maxVaryings = capabilities.maxVaryings || 15;", + " const maxFragmentUniforms = capabilities.maxFragmentUniforms || 224;", + "", + " // Left for the material itself: colour, normal, roughness, metalness,", + " // emissive, ambient occlusion and the environment map.", + " const textureUnitsForMaterials = 8;", + " // Varyings already spent on positions, normals, uvs and fog.", + " const varyingsForGeometry = 12;", + " // Uniform vectors already spent on matrices, material properties and the", + " // uv transforms of a material's own textures.", + " const uniformVectorsForMaterials = 64;", + " // Measured on a MeshStandardMaterial: a point light costs 4 uniform", + " // vectors, a spot light 7, and casting a shadow adds around 11 more on", + " // top of either. Take the dearest of them, since a kind count says how", + " // many kinds a scene uses but not which ones.", + " const uniformVectorsPerLight = 8;", + " const uniformVectorsPerShadow = 12;", + "", + " const availableTextureUnits = Math.max(", + " kindCount, maxTextures - textureUnitsForMaterials);", + " const availableVaryings = Math.max(", + " kindCount, maxVaryings - varyingsForGeometry);", + " const availableUniformVectors = Math.max(", + " 16, maxFragmentUniforms - uniformVectorsForMaterials);", + "", + " // Every shadow caster costs a texture unit and a varying, whichever kind", + " // it is. Keep a share of the texture units back for projected textures.", + " const shadowCount = Math.max(0, Math.min(", + " Math.floor(availableTextureUnits / (kindCount + 1)),", + " Math.floor(availableVaryings / kindCount)", + " ));", + " // What is left bounds how many spot lights can project a texture. Lights", + " // that neither cast a shadow nor project a texture cost no texture unit.", + " const mapCount = Math.max(0,", + " availableTextureUnits - shadowCount * kindCount);", + " // Shadow casters are paid for first, then the uniform vectors left over", + " // decide how many lights of each kind can be lit at all.", + " const uniformVectorsForShadows =", + " shadowCount * kindCount * uniformVectorsPerShadow;", + " const count = Math.max(1, Math.floor(", + " Math.max(uniformVectorsPerLight * kindCount,", + " availableUniformVectors - uniformVectorsForShadows)", + " / (uniformVectorsPerLight * kindCount)));", + "", + " return { shadowCount, mapCount, count };", + "}", + "", + "/**", + " * A capacity that never goes past what the device can take, however high the", + " * game sets its own maximum. Both sides are read through getters, so that", + " * changing the game's maximum at runtime still takes effect, and so that a", + " * device budget recomputed for more light kinds is picked up as well.", + " *", + " * @param {{value: number}} requested", + " * @param {() => number} getDeviceMax", + " * @returns {{value: number}}", + " */", + "function makeDeviceCappedCapacity(requested, getDeviceMax) {", + " return {", + " get value() {", + " return Math.min(requested.value, getDeviceMax());", + " }", + " };", + "}", + "", + "/**", + " * Get the light manager of a scene.", + " * @param {gdjs.RuntimeScene & {__lightManager: LightManager}} runtimeScene", + " */", + "function getLightManager(runtimeScene) {", + " if (!runtimeScene.__lightManager) {", + " // Create the shared manager if necessary.", + " const requestedCount = isInGameEdition", + " ? editorLightCountMax : lightCountMax;", + " const requestedShadowCount = isInGameEdition", + " ? editorLightShadowCountMax : lightShadowCountMax;", + "", + " // The renderer is read anew on every recomputation: it may not", + " // exist yet when the manager is created on the first frame.", + " runtimeScene.__lightManager = new LightManager(", + " requestedCount, requestedShadowCount,", + " kindCount => computeDeviceLightBudget(", + " runtimeScene.getGame().getRenderer().getThreeRenderer(),", + " kindCount));", + " }", + " return runtimeScene.__lightManager;", + "}", + "", + "/**", + " * Lights kept sorted by their distance to the camera, capped to a fixed", + " * number of entries.", + " *", + " * The cap is a *count* and not a weighted cost, on purpose: three.js compiles", + " * the number of lights of each type into its shaders, so a list whose length", + " * changes from one frame to the next forces a shader recompilation every time", + " * a new length is seen. A count based cap keeps the length pinned to", + " * `capacity` for as long as enough lights are candidates.", + " */", + "class CappedLightList {", + " /** @type {Array<{object: LightRuntimeObject, sortDistance: number}>} */", + " objects = [];", + " /** @type {{value: number}} */", + " capacity;", + " /** @type {(object: LightRuntimeObject) => void} */", + " onInsertion;", + " /** @type {(object: LightRuntimeObject) => void} */", + " onDeletion;", + "", + " /**", + " * @param {{value: number}} capacity", + " * @param {(object: LightRuntimeObject) => void} onInsertion", + " * @param {(object: LightRuntimeObject) => void} onDeletion", + " */", + " constructor(capacity, onInsertion, onDeletion) {", + " this.capacity = capacity;", + " this.onInsertion = onInsertion;", + " this.onDeletion = onDeletion;", + " }", + "", + " clear() {", + " this.objects.length = 0;", + " }", + "", + " /** Drop the farthest lights until the list fits its capacity again. */", + " trimToCapacity() {", + " while (this.objects.length > this.capacity.value) {", + " this.onDeletion(this.objects.pop().object);", + " }", + " }", + "", + " /**", + " * @param object {LightRuntimeObject}", + " * @param sortDistance {number} The squared distance to the camera.", + " */", + " insertByDistance(object, sortDistance) {", + " let insertionIndex = 0;", + " for (let index = this.objects.length - 1; index >= 0; index--) {", + " if (sortDistance >= this.objects[index].sortDistance) {", + " insertionIndex = index + 1;", + " break;", + " }", + " }", + " if (insertionIndex >= this.capacity.value) {", + " // Farther away than every light already filling the list.", + " return;", + " }", + "", + " // Make room first, reusing an evicted pair to avoid allocating one", + " // on every frame.", + " let pair = null;", + " while (this.objects.length >= this.capacity.value) {", + " pair = this.objects.pop();", + " this.onDeletion(pair.object);", + " }", + " if (pair) {", + " pair.object = object;", + " pair.sortDistance = sortDistance;", + " }", + " else {", + " pair = { object, sortDistance };", + " }", + " this.objects.splice(insertionIndex, 0, pair);", + " this.onInsertion(object);", + " }", + "}", + "", + "/** @param object {LightRuntimeObject} */", + "const showLight = (object) => { object.__light3D.visible = true; };", + "/** @param object {LightRuntimeObject} */", + "const hideLight = (object) => { object.__light3D.visible = false; };", + "/** @param object {LightRuntimeObject} */", + "const enableShadow = (object) => { object.__light3D.castShadow = true; };", + "/** @param object {LightRuntimeObject} */", + "const disableShadow = (object) => { object.__light3D.castShadow = false; };", + "", + "/**", + " * The lights of a scene, budgeted so that the numbers three.js compiles into", + " * its shaders stay put.", + " *", + " * three.js keys its shader programs on how many lights of each kind it can", + " * see - NUM_POINT_LIGHTS, NUM_SPOT_LIGHTS, NUM_SPOT_LIGHT_MAPS and the", + " * matching shadow counts. A single budget shared by every kind keeps the", + " * *total* pinned to the cap but lets the mix drift as the camera moves, and", + " * each mix that has not been seen before costs a shader compilation - a", + " * stutter the player feels. So each kind gets its own budget instead, which", + " * pins each of those numbers individually.", + " */", + "class LightManager {", + " /** @type {Map} Visible lights, by light kind. */", + " visibleLists = new Map();", + " /** @type {Map} Shadow casters, by light kind. */", + " shadowLists = new Map();", + " /** @type {Map} Lit light capacity, by light kind. */", + " maxCountByKind;", + " /** @type {Map} Shadow caster capacity, by light kind. */", + " shadowCountByKind;", + " /** @type {Set} The light kinds this scene has actually used. */", + " usedKinds = new Set();", + " /** @type {{shadowCount: number, mapCount: number, count: number}} */", + " deviceBudget;", + " /** @type {(kindCount: number) => {shadowCount: number, mapCount: number, count: number}} */", + " _computeDeviceBudget;", + " /** @type {{value: number}} */", + " _requestedCount;", + " /** @type {{value: number}} */", + " _requestedShadowCount;", + "", + " /**", + " * @param maxCount {{value: number}} The maximum number of lit lights, for", + " * each light kind, as the game asked for it.", + " * @param shadowCount {{value: number}} The maximum number of shadow", + " * casting lights, for each light kind, as the game asked for it.", + " * @param computeDeviceBudget {(kindCount: number) => {shadowCount: number, mapCount: number, count: number}}", + " * What the device can take, for a given number of light kinds.", + " */", + " constructor(maxCount, shadowCount, computeDeviceBudget) {", + " this._computeDeviceBudget = computeDeviceBudget;", + " this._requestedCount = maxCount;", + " this._requestedShadowCount = shadowCount;", + " // A scene that uses lights at all uses at least one kind of them.", + " this.deviceBudget = computeDeviceBudget(1);", + "", + " // Spot lights that project a texture already spend a texture unit on", + " // that texture, so they get the tighter of the two budgets.", + " this.maxCountByKind = new Map([", + " ['point', makeDeviceCappedCapacity(", + " maxCount, () => this.deviceBudget.count)],", + " ['spot', makeDeviceCappedCapacity(", + " maxCount, () => this.deviceBudget.count)],", + " ['spotWithMap', makeDeviceCappedCapacity(maxCount, () => Math.min(", + " this.deviceBudget.count, this.deviceBudget.mapCount))],", + " ]);", + " this.shadowCountByKind = new Map([", + " ['point', makeDeviceCappedCapacity(", + " shadowCount, () => this.deviceBudget.shadowCount)],", + " ['spot', makeDeviceCappedCapacity(", + " shadowCount, () => this.deviceBudget.shadowCount)],", + " ['spotWithMap', makeDeviceCappedCapacity(", + " shadowCount, () => this.deviceBudget.shadowCount)],", + " ]);", + " }", + "", + " /**", + " * Take note that the scene uses lights of this kind, sharing the device", + " * budget between one more kind if it had not been seen before.", + " *", + " * A kind can only ever be added, never dropped: a light that goes away for", + " * a while must not give the others a wider budget, or the numbers three.js", + " * compiles into its shaders would move again.", + " *", + " * @param kind {string}", + " */", + " _useKind(kind) {", + " if (this.usedKinds.has(kind)) {", + " return;", + " }", + " this.usedKinds.add(kind);", + " this.deviceBudget = this._computeDeviceBudget(this.usedKinds.size);", + "", + " // The budget just shrank: evict the lights that no longer fit, so", + " // that even this frame stays within what the device can take.", + " for (const list of this.visibleLists.values()) {", + " list.trimToCapacity();", + " }", + " for (const list of this.shadowLists.values()) {", + " list.trimToCapacity();", + " }", + "", + " if (this.deviceBudget.count < this._requestedCount.value", + " || this.deviceBudget.shadowCount", + " < this._requestedShadowCount.value) {", + " logger.info(", + " 'This device limits 3D lights to ' + this.deviceBudget.count", + " + ' per kind (' + this.deviceBudget.shadowCount", + " + ' casting a shadow, ' + this.deviceBudget.mapCount", + " + ' projecting a texture), now that ' + this.usedKinds.size", + " + ' kind(s) of light share its budget. Going over what it '", + " + 'reports would stop the shaders from linking.'", + " );", + " }", + " }", + "", + " clear() {", + " for (const list of this.visibleLists.values()) {", + " list.clear();", + " }", + " for (const list of this.shadowLists.values()) {", + " list.clear();", + " }", + " }", + "", + " /**", + " * The kind of a light, as far as the shaders are concerned. Lights of", + " * different kinds are counted separately by three.js, so they must be", + " * budgeted separately too.", + " * @param light {THREE.SpotLight | THREE.PointLight}", + " * @returns {string}", + " */", + " static getLightKind(light) {", + " //@ts-ignore - `isSpotLight` is set by three.js on SpotLight instances.", + " if (!light.isSpotLight) {", + " return 'point';", + " }", + " // A projected texture adds to NUM_SPOT_LIGHT_MAPS, so a spot light", + " // that has one is a different kind from a spot light that has not.", + " //@ts-ignore - only spot lights have a projected texture.", + " return light.map ? 'spotWithMap' : 'spot';", + " }", + "", + " /**", + " * @param lists {Map}", + " * @param kind {string}", + " * @param capacity {{value: number}}", + " * @param onInsertion {(object: LightRuntimeObject) => void}", + " * @param onDeletion {(object: LightRuntimeObject) => void}", + " * @returns {CappedLightList}", + " */", + " static _getListForKind(lists, kind, capacity, onInsertion, onDeletion) {", + " let list = lists.get(kind);", + " if (!list) {", + " list = new CappedLightList(capacity, onInsertion, onDeletion);", + " lists.set(kind, list);", + " }", + " return list;", + " }", + "", + " /**", + " * @param object {LightRuntimeObject}", + " * @param distance {number} The squared distance to the camera.", + " */", + " applyVisibilityAndShadow(object, distance) {", + " const light = object.__light3D;", + " const kind = LightManager.getLightKind(light);", + " this._useKind(kind);", + "", + " if (object._getIsCastingShadow()) {", + " LightManager._getListForKind(", + " this.shadowLists, kind, this.shadowCountByKind.get(kind),", + " enableShadow, disableShadow", + " ).insertByDistance(object, distance);", + " }", + " LightManager._getListForKind(", + " this.visibleLists, kind, this.maxCountByKind.get(kind),", + " showLight, hideLight", + " ).insertByDistance(object, distance);", + " }", + "}", + "", + "//@ts-ignore", + "gdjs.__light3DExtension = {", + " Light3DRenderer,", + " lightCountMax,", + " lightShadowCountMax,", + "}" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "the maximum number of nearest lights displayed simultaneously, counted separately for each kind of light (point lights, spot lights, spot lights projecting a texture). Devices that can't take that many lights enforce a lower limit.", + "fullName": "Max lights count", + "functionType": "ExpressionAndCondition", + "name": "LightCountMax", + "sentence": "max lights count", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Light3D::DefineHelperClasses" + }, + "parameters": [ + "", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": "eventsFunctionContext.returnValue = gdjs.__light3DExtension.lightCountMax.value;", + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "LightCountMax", + "name": "SetLightCountMax", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Light3D::DefineHelperClasses" + }, + "parameters": [ + "", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const value = eventsFunctionContext.getArgument(\"Value\");", + "", + "gdjs.__light3DExtension.lightCountMax.value = value;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "the maximum number of nearest lights displayed with shadow simultaneously, counted separately for each kind of light (point lights, spot lights, spot lights projecting a texture). Devices that can't take that many shadows enforce a lower limit.", + "fullName": "Max lights with shadow count", + "functionType": "ExpressionAndCondition", + "name": "LightShadowCountMax", + "sentence": "max lights with shadow count", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Light3D::DefineHelperClasses" + }, + "parameters": [ + "", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": "eventsFunctionContext.returnValue = gdjs.__light3DExtension.lightShadowCountMax.value;", + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "LightShadowCountMax", + "name": "SetLightShadowCountMax", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Light3D::DefineHelperClasses" + }, + "parameters": [ + "", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const value = eventsFunctionContext.getArgument(\"Value\");", + "", + "gdjs.__light3DExtension.lightShadowCountMax.value = value;" + ], + "parameterObjects": "", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "DefineHelperClasses" + }, + { + "functionName": "DefineSpotLightHelperClasses" + }, + { + "functionName": "DefinePointLightHelperClasses" + }, + { + "functionName": "LightCountMax" + }, + { + "functionName": "SetLightCountMax" + }, + { + "functionName": "LightShadowCountMax" + }, + { + "functionName": "SetLightShadowCountMax" + } + ] + }, + "eventsBasedBehaviors": [], + "eventsBasedObjects": [ + { + "areaMaxX": 20, + "areaMaxY": 20, + "areaMaxZ": 20, + "areaMinX": -20, + "areaMinY": -20, + "areaMinZ": -20, + "defaultName": "SpotLight", + "description": "Light up a cone like a flashlight.", + "fullName": "3D spot light", + "helpPath": "", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0ibWRpLWZsYXNobGlnaHQiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNOSwxMEw2LDVIMThMMTUsMTBIOU0xOCw0SDZWMkgxOFY0TTksMjJWMTFIMTVWMjJIOU0xMiwxM0ExLDEgMCAwLDAgMTEsMTRBMSwxIDAgMCwwIDEyLDE1QTEsMSAwIDAsMCAxMywxNEExLDEgMCAwLDAgMTIsMTNaIiAvPjwvc3ZnPg==", + "is3D": true, + "isUsingLegacyInstancesRenderer": false, + "name": "SpotLight3D", + "previewIconUrl": "https://asset-resources.gdevelop.io/public-resources/Icons/b627f8e676b3aac26945b2c38db0cfa787d34d2eff23755d4eb1289452f6cd28_flashlight.svg", + "objects": [ + { + "assetStoreId": "", + "name": "Placeholder", + "persistentUuid": "6786eefd-3c18-4fcb-b3ae-95b07f953045", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 80, + "height": 80, + "depth": 80, + "enableTextureTransparency": false, + "facesOrientation": "Z", + "frontFaceResourceName": "", + "backFaceResourceName": "", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "", + "rightFaceResourceName": "", + "topFaceResourceName": "", + "bottomFaceResourceName": "", + "frontFaceVisible": true, + "backFaceVisible": true, + "leftFaceVisible": true, + "rightFaceVisible": true, + "topFaceVisible": true, + "bottomFaceVisible": true, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "materialType": "Basic", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": false + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Placeholder" + } + ] + }, + "objectsGroups": [], + "layers": [ + { + "ambientLightColorB": 200, + "ambientLightColorG": 200, + "ambientLightColorR": 200, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "", + "renderingType": "", + "visibility": true, + "cameras": [ + { + "defaultSize": true, + "defaultViewport": true, + "height": 0, + "viewportBottom": 1, + "viewportLeft": 0, + "viewportRight": 1, + "viewportTop": 0, + "width": 0 + } + ], + "effects": [] + } + ], + "instances": [ + { + "angle": 0, + "customSize": true, + "depth": 40, + "height": 40, + "layer": "", + "name": "Placeholder", + "persistentUuid": "1310c768-04d4-4133-98d9-37d836f8a990", + "width": 40, + "x": -20, + "y": -20, + "z": -20, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + } + ], + "editionSettings": { + "grid": false, + "gridType": "rectangular", + "gridWidth": 32, + "gridHeight": 32, + "gridDepth": 32, + "gridOffsetX": 0, + "gridOffsetY": 0, + "gridOffsetZ": 0, + "gridColor": 10401023, + "gridAlpha": 0.8, + "snap": false, + "zoomFactor": 9.06473532531222, + "windowMask": false, + "selectedLayer": "", + "gameEditorMode": "instances-editor" + }, + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onCreated", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Light3D::DefineHelperClasses" + }, + "parameters": [ + "", + "" + ] + }, + { + "type": { + "value": "Light3D::DefineSpotLightHelperClasses" + }, + "parameters": [ + "", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const {", + " Light3DRenderer,", + " //@ts-ignore", + "} = gdjs.__light3DExtension;", + "const {", + " SpotLightAdapter,", + " SpotLightHelper,", + " //@ts-ignore", + "} = gdjs.__light3DExtension.spot;", + "", + "/** @type {gdjs.CustomRuntimeObject3D} */", + "//@ts-ignore", + "const object = objects[0];", + "", + "const game = runtimeScene.getGame();", + "", + "// This is a hack that may break in future releases.", + "// Replace the group that would hold children objects by the light.", + "const layer = object.getInstanceContainer().getLayer(object.getLayer());", + "const group = object.getRenderer()._threeGroup;", + "layer.getRenderer().remove3DRendererObject(group);", + "", + "const spotLight = new THREE.SpotLight(0xffffff);", + "spotLight.position.copy(group.position);", + "spotLight.rotation.copy(group.rotation);", + "spotLight.add(spotLight.target);", + "spotLight.target.position.x = 100;", + "spotLight.up.set(0, 0, 1);", + "spotLight.shadow.camera.up.set(0, 0, 1);", + "//@ts-ignore", + "object.__light3D = spotLight;", + "//@ts-ignore", + "object.__spotLightAdapter = new SpotLightAdapter(object, spotLight);", + "", + "const spotLight3DRenderer = new Light3DRenderer(object, object._instanceContainer, object.getInstanceContainer());", + "object._renderer = spotLight3DRenderer;", + "if (game.isInGameEdition && game.isInGameEdition()) {", + " const spotLightHelper = new SpotLightHelper(object);", + " spotLightHelper.rotation.order = 'ZYX';", + " spotLightHelper.add(spotLight);", + " spotLight3DRenderer._threeGroup = spotLightHelper;", + " layer.getRenderer().add3DRendererObject(spotLightHelper);", + "}", + "else {", + " spotLight3DRenderer._threeGroup = spotLight;", + " layer.getRenderer().add3DRendererObject(spotLight);", + "}", + "", + "spotLight.updateMatrixWorld(true);", + "", + "// Allow to tween the light color.", + "//@ts-ignore", + "if (!object.setColor && !object.getColor) {", + " const prototype = Object.getPrototypeOf(object);", + " prototype.setColor = function(tint) {", + " this._setColor(tint);", + " this.__spotLightAdapter.setColor(tint);", + " }", + " prototype.getColor = function() {", + " return this._getColor(eventsFunctionContext);", + " }", + "}", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Light3D::SpotLight3D::UpdateFromProperties" + }, + "parameters": [ + "Object", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onDestroy", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.CustomRuntimeObject} */", + "const object = objects[0];", + "// Here runtimeScene is the gdjs.CustomRuntimeObjectInstanceContainer inside the custom object.", + "const gameScene = object.getRuntimeScene();", + "", + "object.__light3D.dispose();", + "object.get3DRendererObject().dispose();", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onHotReloading", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Light3D::SpotLight3D::UpdateFromProperties" + }, + "parameters": [ + "Object", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Update from properties.", + "fullName": "Update from properties", + "functionType": "Action", + "name": "UpdateFromProperties", + "private": true, + "sentence": "Update from properties of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Light3D::SpotLight3D::SetColor" + }, + "parameters": [ + "Object", + "=", + "Color", + "" + ] + }, + { + "type": { + "value": "Light3D::SpotLight3D::SetIntensity" + }, + "parameters": [ + "Object", + "=", + "Intensity", + "" + ] + }, + { + "type": { + "value": "Light3D::SpotLight3D::SetDecay" + }, + "parameters": [ + "Object", + "=", + "Decay", + "" + ] + }, + { + "type": { + "value": "Light3D::SpotLight3D::SetConeLength" + }, + "parameters": [ + "Object", + "=", + "ConeLength", + "" + ] + }, + { + "type": { + "value": "Light3D::SpotLight3D::SetConeAngle" + }, + "parameters": [ + "Object", + "=", + "ConeAngle", + "" + ] + }, + { + "type": { + "value": "Light3D::SpotLight3D::SetSmoothing" + }, + "parameters": [ + "Object", + "=", + "Smoothing", + "" + ] + }, + { + "type": { + "value": "Light3D::SpotLight3D::SetShadowQuality" + }, + "parameters": [ + "Object", + "=", + "ShadowQuality", + "" + ] + }, + { + "type": { + "value": "Light3D::SpotLight3D::SetShadowCameraNearPlane" + }, + "parameters": [ + "Object", + "=", + "ShadowCameraNearPlane", + "" + ] + }, + { + "type": { + "value": "Light3D::SpotLight3D::SetShadowCameraFarPlane" + }, + "parameters": [ + "Object", + "=", + "ShadowCameraFarPlane", + "" + ] + }, + { + "type": { + "value": "Light3D::SpotLight3D::SetShadowBias" + }, + "parameters": [ + "Object", + "=", + "ShadowBias", + "" + ] + }, + { + "type": { + "value": "Light3D::SpotLight3D::UpdateImage" + }, + "parameters": [ + "Object", + "" + ] + }, + { + "type": { + "value": "Light3D::SpotLight3D::UpdateHelper" + }, + "parameters": [ + "Object", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsCastingShadow", + "=", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "Light3D::SpotLight3D::SetCastingShadow" + }, + "parameters": [ + "Object", + "no", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsCastingShadow", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "Light3D::SpotLight3D::SetCastingShadow" + }, + "parameters": [ + "Object", + "yes", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "Update helper", + "functionType": "Action", + "name": "UpdateHelper", + "private": true, + "sentence": "Update graphical helper of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const game = runtimeScene.getGame();", + "if (game.isInGameEdition && game.isInGameEdition()) {", + " const spotLightHelper = objects[0].get3DRendererObject();", + " spotLightHelper.update();", + "}", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "Update image", + "functionType": "Action", + "name": "UpdateImage", + "private": true, + "sentence": "Update the image of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.CustomRuntimeObject3D} */\r", + "const object = objects[0];\r", + "const resourceName = object._getImage();\r", + "object.__spotLightAdapter.setImage(resourceName);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the cone angle of the light.", + "fullName": "Cone angle", + "functionType": "ExpressionAndCondition", + "name": "ConeAngle", + "sentence": "the cone angle", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ConeAngle" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "ConeAngle", + "name": "SetConeAngle", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ConeAngle", + "=", + "Value" + ] + }, + { + "type": { + "value": "Light3D::SpotLight3D::ApplyShadowBias" + }, + "parameters": [ + "Object", + "ShadowBias", + "ShadowQuality", + "ConeAngle", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const coneAngle = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__spotLightAdapter.setConeAngle(coneAngle);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the color of the light.", + "fullName": "Color", + "functionType": "ExpressionAndCondition", + "name": "Color", + "sentence": "the color", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnString" + }, + "parameters": [ + "Color" + ] + } + ] + } + ], + "expressionType": { + "type": "color" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Color", + "name": "SetColor", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Color", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const color = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__spotLightAdapter.setColor(color);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the smoothing of the light. Percent of the spotlight cone that is attenuated due to penumbra (between 0 and 1).", + "fullName": "Smoothing", + "functionType": "ExpressionAndCondition", + "name": "Smoothing", + "sentence": "the smoothing", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Smoothing" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Smoothing", + "name": "SetSmoothing", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Smoothing", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__spotLightAdapter.setSmoothing(value);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the intensity of the light.", + "fullName": "Intensity", + "functionType": "ExpressionAndCondition", + "name": "Intensity", + "sentence": "the intensity", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Intensity" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Intensity", + "name": "SetIntensity", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Intensity", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__spotLightAdapter.setIntensity(value);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the decay of the light. The amount the light dims along the distance of the light.", + "fullName": "Decay", + "functionType": "ExpressionAndCondition", + "name": "Decay", + "sentence": "the decay", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Decay" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Decay", + "name": "SetDecay", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Decay", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__spotLightAdapter.setDecay(value);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the light is casting shadows.", + "fullName": "Shadow casting", + "functionType": "Condition", + "group": "3D spot light shadow configuration", + "name": "IsCastingShadow", + "sentence": "_PARAM0_ casting shadows", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsCastingShadow", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Change if the light is casting shadows.", + "fullName": "Shadow casting", + "functionType": "Action", + "group": "3D spot light shadow configuration", + "name": "SetCastingShadow", + "sentence": "_PARAM0_ casting shadows: _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "False", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsCastingShadow", + "False", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsCastingShadow", + "True", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__spotLightAdapter.setCastingShadow(value);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Light3D::SpotLight3D::SetConeLength" + }, + "parameters": [ + "Object", + "=", + "ConeLength", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + }, + { + "defaultValue": "yes", + "description": "Shadow casting", + "name": "Value", + "optional": true, + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "Rotate the light to light up a position.", + "fullName": "Look at position", + "functionType": "Action", + "group": "Angle", + "name": "LookAtPosition", + "sentence": "_PARAM0_ look at _PARAM1_ ; _PARAM2_ ; _PARAM3_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const targetX = eventsFunctionContext.getArgument(\"TargetX\");\r", + "const targetY = eventsFunctionContext.getArgument(\"TargetY\");\r", + "const targetZ = eventsFunctionContext.getArgument(\"TargetZ\");\r", + "\r", + "object.__spotLightAdapter.lookAtPosition(targetX, targetY, targetZ);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + }, + { + "description": "Target X", + "name": "TargetX", + "type": "expression" + }, + { + "description": "Target Y", + "name": "TargetY", + "type": "expression" + }, + { + "description": "Target Z", + "name": "TargetZ", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "Rotate the light to light up an object.", + "fullName": "Look at object", + "functionType": "Action", + "group": "Angle", + "name": "LookAtObject", + "sentence": "_PARAM0_ look at _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Light3D::SpotLight3D::LookAtPosition" + }, + "parameters": [ + "Object", + "Target.CenterX()", + "Target.CenterY()", + "Target.Object3D::CenterZ()", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + }, + { + "description": "Object", + "name": "Target", + "type": "objectList" + }, + { + "description": "3D capability", + "name": "Object3D", + "supplementaryInformation": "Scene3D::Base3DBehavior", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "description": "the shadow quality of the light.", + "fullName": "Shadow quality", + "functionType": "ExpressionAndCondition", + "group": "3D spot light shadow configuration", + "name": "ShadowQuality", + "sentence": "the shadow quality", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnString" + }, + "parameters": [ + "ShadowQuality" + ] + } + ] + } + ], + "expressionType": { + "supplementaryInformation": "[\"Low\",\"Medium\",\"High\"]", + "type": "stringWithSelector" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "ShadowQuality", + "group": "3D spot light shadow configuration", + "name": "SetShadowQuality", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "ShadowQuality", + "=", + "Value" + ] + }, + { + "type": { + "value": "Light3D::SpotLight3D::ApplyShadowBias" + }, + "parameters": [ + "Object", + "ShadowBias", + "ShadowQuality", + "ConeAngle", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__spotLightAdapter.setShadowQuality(value);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the shadow camera near plane of the light.", + "fullName": "Shadow camera near plane", + "functionType": "ExpressionAndCondition", + "group": "3D spot light shadow configuration", + "name": "ShadowCameraNearPlane", + "sentence": "the shadow camera near plane", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ShadowCameraNearPlane" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "ShadowCameraNearPlane", + "group": "3D spot light shadow configuration", + "name": "SetShadowCameraNearPlane", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ShadowCameraNearPlane", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__spotLightAdapter.setShadowCameraNearPlane(value);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the shadow camera far plane of the light.", + "fullName": "Shadow camera far plane", + "functionType": "ExpressionAndCondition", + "group": "3D spot light shadow configuration", + "name": "ShadowCameraFarPlane", + "sentence": "the shadow camera far plane", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ShadowCameraFarPlane" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "ShadowCameraFarPlane", + "group": "3D spot light shadow configuration", + "name": "SetShadowCameraFarPlane", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ShadowCameraFarPlane", + "=", + "Value" + ] + }, + { + "type": { + "value": "Light3D::SpotLight3D::ApplyShadowCameraFarPlane" + }, + "parameters": [ + "Object", + "min(Value, ConeLength)", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the cone length of the light. 0 means no limit.", + "fullName": "Cone length", + "functionType": "ExpressionAndCondition", + "name": "ConeLength", + "sentence": "the cone length", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ConeLength" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "ConeLength", + "name": "SetConeLength", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ConeLength", + "=", + "Value" + ] + } + ], + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__spotLightAdapter.setConeLength(value);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Three.js reduces the far plane to match the light range.\nSo, we need to set it again or it will stay at the lowest value the range took.\nWe do the min() on our side to in order:\n- to avoid a side effect when Three.js is upgraded\n- because Three.js keeps the old value in cache and doesn't apply it back unless we set the lower value explicitly ourselves." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Light3D::SpotLight3D::ApplyShadowCameraFarPlane" + }, + "parameters": [ + "Object", + "min(Value, ShadowCameraFarPlane)", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "Apply shadow camera far plane", + "functionType": "Action", + "group": "3D spot light shadow configuration", + "name": "ApplyShadowCameraFarPlane", + "private": true, + "sentence": "Apply shadow camera far plane of _PARAM0_ to _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__spotLightAdapter.setShadowCameraFarPlane(value);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + }, + { + "description": "Value", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the shadow bias of the light. Use this to avoid \"shadow acne\" due to depth buffer precision. Choose a value small enough like 0.001 to avoid creating distance between shadows and objects but not too small to avoid shadow glitches on low/medium quality. This value is used for high quality, and multiplied by 2 for medium quality and 4 for low quality.", + "fullName": "Shadow bias", + "functionType": "ExpressionAndCondition", + "group": "3D spot light shadow configuration", + "name": "ShadowBias", + "sentence": "the shadow bias", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ShadowBias" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "ShadowBias", + "group": "3D spot light shadow configuration", + "name": "SetShadowBias", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ShadowBias", + "=", + "Value" + ] + }, + { + "type": { + "value": "Light3D::SpotLight3D::ApplyShadowBias" + }, + "parameters": [ + "Object", + "Value", + "ShadowQuality", + "ConeAngle", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "Apply shadow bias", + "functionType": "Action", + "group": "3D spot light shadow configuration", + "name": "ApplyShadowBias", + "private": true, + "sentence": "Apply shadow bias of _PARAM0_ to _PARAM1_ for a _PARAM2_ quality and cone angle _PARAM3_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "const quality = eventsFunctionContext.getArgument(\"Quality\");\r", + "const coneAngle = eventsFunctionContext.getArgument(\"Angle\");\r", + "\r", + "object.__spotLightAdapter.setShadowBias(value, quality, coneAngle);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::SpotLight3D", + "type": "object" + }, + { + "description": "Value", + "name": "Value", + "type": "expression" + }, + { + "description": "Quality", + "name": "Quality", + "type": "string" + }, + { + "description": "Cone angle", + "name": "Angle", + "type": "expression" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onCreated" + }, + { + "functionName": "onDestroy" + }, + { + "functionName": "onHotReloading" + }, + { + "functionName": "UpdateFromProperties" + }, + { + "functionName": "UpdateHelper" + }, + { + "functionName": "UpdateImage" + }, + { + "folderName": "Angle", + "children": [ + { + "functionName": "LookAtPosition" + }, + { + "functionName": "LookAtObject" + } + ] + }, + { + "functionName": "Color" + }, + { + "functionName": "SetColor" + }, + { + "functionName": "Intensity" + }, + { + "functionName": "SetIntensity" + }, + { + "functionName": "Decay" + }, + { + "functionName": "SetDecay" + }, + { + "functionName": "ConeLength" + }, + { + "functionName": "SetConeLength" + }, + { + "functionName": "ConeAngle" + }, + { + "functionName": "SetConeAngle" + }, + { + "functionName": "Smoothing" + }, + { + "functionName": "SetSmoothing" + }, + { + "folderName": "3D spot light shadow configuration", + "children": [ + { + "functionName": "IsCastingShadow" + }, + { + "functionName": "SetCastingShadow" + }, + { + "functionName": "ShadowQuality" + }, + { + "functionName": "SetShadowQuality" + }, + { + "functionName": "ShadowCameraNearPlane" + }, + { + "functionName": "SetShadowCameraNearPlane" + }, + { + "functionName": "ShadowCameraFarPlane" + }, + { + "functionName": "SetShadowCameraFarPlane" + }, + { + "functionName": "ApplyShadowCameraFarPlane" + }, + { + "functionName": "ShadowBias" + }, + { + "functionName": "SetShadowBias" + }, + { + "functionName": "ApplyShadowBias" + } + ] + } + ] + }, + "propertyDescriptors": [ + { + "value": "255;255;255", + "type": "Color", + "label": "Color", + "name": "Color" + }, + { + "value": "30", + "type": "Number", + "unit": "DegreeAngle", + "label": "Cone angle", + "group": "Cone", + "name": "ConeAngle" + }, + { + "value": "1", + "type": "Number", + "label": "Intensity", + "name": "Intensity" + }, + { + "value": "1", + "type": "Number", + "label": "Smoothing", + "description": "Percent of the spotlight cone that is attenuated due to penumbra (between 0 and 1).", + "group": "Cone", + "name": "Smoothing" + }, + { + "value": "2", + "type": "Number", + "label": "Decay", + "description": "The amount the light dims along the distance of the light.", + "name": "Decay" + }, + { + "value": "", + "type": "Resource", + "label": "Image", + "description": "Shadow casting must be enabled for the image to have any effect.", + "group": "Shadow", + "extraInformation": [ + "image" + ], + "choices": [], + "hidden": true, + "name": "Image" + }, + { + "value": "true", + "type": "Boolean", + "label": "Shadow casting", + "group": "Shadow", + "name": "IsCastingShadow" + }, + { + "value": "Medium", + "type": "Choice", + "label": "Shadow quality", + "group": "Shadow", + "choices": [ + { + "label": "Low", + "value": "Low" + }, + { + "label": "Medium", + "value": "Medium" + }, + { + "label": "High", + "value": "High" + }, + { + "label": "Very high", + "value": "VeryHigh" + } + ], + "name": "ShadowQuality" + }, + { + "value": "20", + "type": "Number", + "unit": "Pixel", + "label": "Shadow camera near plane", + "group": "Shadow", + "advanced": true, + "name": "ShadowCameraNearPlane" + }, + { + "value": "2000", + "type": "Number", + "unit": "Pixel", + "label": "Shadow camera far plane", + "group": "Shadow", + "advanced": true, + "name": "ShadowCameraFarPlane" + }, + { + "value": "2000", + "type": "Number", + "unit": "Pixel", + "label": "Cone length", + "description": "0 means no limit.", + "group": "Cone", + "name": "ConeLength" + }, + { + "value": "0", + "type": "Number", + "label": "Shadow bias", + "description": "Use this to avoid \"shadow acne\" due to depth buffer precision. Choose a value small enough like 0.001 to avoid creating distance between shadows and objects but not too small to avoid shadow glitches on low/medium quality. This value is used for high quality, and multiplied by 2 for medium quality and 4 for low quality.", + "group": "Shadow", + "advanced": true, + "name": "ShadowBias" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "Color" + }, + { + "propertyName": "Intensity" + }, + { + "propertyName": "Decay" + }, + { + "folderName": "Cone", + "children": [ + { + "propertyName": "ConeAngle" + }, + { + "propertyName": "ConeLength" + }, + { + "propertyName": "Smoothing" + } + ] + }, + { + "folderName": "Shadow", + "children": [ + { + "propertyName": "IsCastingShadow" + }, + { + "propertyName": "ShadowQuality" + }, + { + "propertyName": "Image" + }, + { + "propertyName": "ShadowCameraNearPlane" + }, + { + "propertyName": "ShadowCameraFarPlane" + }, + { + "propertyName": "ShadowBias" + } + ] + } + ] + } + }, + { + "areaMaxX": 20, + "areaMaxY": 20, + "areaMaxZ": 20, + "areaMinX": -20, + "areaMinY": -20, + "areaMinZ": -20, + "defaultName": "PointLight", + "description": "Light up in all directions like a fire.", + "fullName": "3D point light", + "helpPath": "", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0ibWRpLXRvcmNoIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTguNiA5LjZDOSAxMC4yIDkuNSAxMC43IDEwLjIgMTFIMTQuMkMxNC41IDEwLjkgMTQuNyAxMC43IDE0LjkgMTAuNUMxNS45IDkuNSAxNi4zIDggMTUuOCA2LjdMMTUuNyA2LjVDMTUuNiA2LjIgMTUuNCA2IDE1LjIgNS44QzE1LjEgNS42IDE0LjkgNS41IDE0LjggNS4zQzE0LjQgNSAxNCA0LjcgMTMuNiA0LjNDMTIuNyAzLjQgMTIuNiAyIDEzLjEgMUMxMi42IDEuMSAxMi4xIDEuNCAxMS43IDEuOEMxMC4yIDMgOS42IDUuMSAxMC4zIDdWNy4yQzEwLjMgNy4zIDEwLjIgNy40IDEwLjEgNy41QzEwIDcuNiA5LjggNy41IDkuNyA3LjRMOS42IDcuM0M5IDYuNSA4LjkgNS4zIDkuMyA0LjNDOC40IDUuMSA3LjkgNi40IDggNy43QzggOCA4LjEgOC4zIDguMiA4LjZDOC4yIDguOSA4LjQgOS4zIDguNiA5LjZNMTIuMyA4LjFDMTIuNCA3LjYgMTIuMiA3LjIgMTIuMSA2LjhDMTIgNi40IDEyIDYgMTIuMiA1LjZMMTIuNSA2LjJDMTIuOSA2LjggMTMuNiA3IDEzLjggNy44VjguMUMxMy44IDguNiAxMy42IDkuMSAxMy4zIDkuNEMxMy4xIDkuNSAxMi45IDkuNyAxMi43IDkuN0MxMi4xIDkuOSAxMS40IDkuNiAxMSA5LjJDMTEuOCA5LjIgMTIuMiA4LjYgMTIuMyA4LjFNMTUgMTJWMTRIMTRMMTMgMjJIMTFMMTAgMTRIOVYxMkgxNVoiIC8+PC9zdmc+", + "is3D": true, + "isUsingLegacyInstancesRenderer": false, + "name": "PointLight3D", + "previewIconUrl": "https://asset-resources.gdevelop.io/public-resources/Icons/bf9158c96f4346dabd9e8ae0ddd737809652797812eb50376bae62463ac7fc42_torch.svg", + "objects": [ + { + "assetStoreId": "", + "name": "Placeholder", + "persistentUuid": "6786eefd-3c18-4fcb-b3ae-95b07f953045", + "type": "Scene3D::Cube3DObject", + "variables": [], + "effects": [], + "behaviors": [], + "content": { + "width": 80, + "height": 80, + "depth": 80, + "enableTextureTransparency": false, + "facesOrientation": "Z", + "frontFaceResourceName": "", + "backFaceResourceName": "", + "backFaceUpThroughWhichAxisRotation": "X", + "leftFaceResourceName": "", + "rightFaceResourceName": "", + "topFaceResourceName": "", + "bottomFaceResourceName": "", + "frontFaceVisible": true, + "backFaceVisible": true, + "leftFaceVisible": true, + "rightFaceVisible": true, + "topFaceVisible": true, + "bottomFaceVisible": true, + "frontFaceResourceRepeat": false, + "backFaceResourceRepeat": false, + "leftFaceResourceRepeat": false, + "rightFaceResourceRepeat": false, + "topFaceResourceRepeat": false, + "bottomFaceResourceRepeat": false, + "materialType": "Basic", + "tint": "255;255;255", + "isCastingShadow": false, + "isReceivingShadow": false + } + } + ], + "objectsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "objectName": "Placeholder" + } + ] + }, + "objectsGroups": [], + "layers": [ + { + "ambientLightColorB": 200, + "ambientLightColorG": 200, + "ambientLightColorR": 200, + "camera2DPlaneMaxDrawingDistance": 5000, + "camera3DFarPlaneDistance": 10000, + "camera3DFieldOfView": 45, + "camera3DNearPlaneDistance": 3, + "cameraType": "", + "followBaseLayerCamera": false, + "isLightingLayer": false, + "isLocked": false, + "name": "", + "renderingType": "", + "visibility": true, + "cameras": [ + { + "defaultSize": true, + "defaultViewport": true, + "height": 0, + "viewportBottom": 1, + "viewportLeft": 0, + "viewportRight": 1, + "viewportTop": 0, + "width": 0 + } + ], + "effects": [] + } + ], + "instances": [ + { + "angle": 0, + "customSize": true, + "depth": 40, + "height": 40, + "layer": "", + "name": "Placeholder", + "persistentUuid": "1310c768-04d4-4133-98d9-37d836f8a990", + "width": 40, + "x": -20, + "y": -20, + "z": -20, + "zOrder": 1, + "numberProperties": [], + "stringProperties": [], + "initialVariables": [] + } + ], + "editionSettings": { + "grid": false, + "gridType": "rectangular", + "gridWidth": 32, + "gridHeight": 32, + "gridDepth": 32, + "gridOffsetX": 0, + "gridOffsetY": 0, + "gridOffsetZ": 0, + "gridColor": 10401023, + "gridAlpha": 0.8, + "snap": false, + "zoomFactor": 9.06473532531222, + "windowMask": false, + "selectedLayer": "", + "gameEditorMode": "instances-editor" + }, + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onCreated", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Light3D::DefineHelperClasses" + }, + "parameters": [ + "", + "" + ] + }, + { + "type": { + "value": "Light3D::DefinePointLightHelperClasses" + }, + "parameters": [ + "", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const {", + " Light3DRenderer,", + " //@ts-ignore", + "} = gdjs.__light3DExtension;", + "const {", + " PointLightAdapter,", + " PointLightHelper,", + " //@ts-ignore", + "} = gdjs.__light3DExtension.point;", + "", + "/** @type {gdjs.CustomRuntimeObject3D} */", + "//@ts-ignore", + "const object = objects[0];", + "", + "const game = runtimeScene.getGame();", + "", + "// This is a hack that may break in future releases.", + "// Replace the group that would hold children objects by the light.", + "const layer = object.getInstanceContainer().getLayer(object.getLayer());", + "const group = object.getRenderer()._threeGroup;", + "layer.getRenderer().remove3DRendererObject(group);", + "", + "const pointLight = new THREE.PointLight(0xffffff);", + "pointLight.position.copy(group.position);", + "pointLight.rotation.copy(group.rotation);", + "pointLight.up.set(0, 0, 1);", + "pointLight.shadow.camera.up.set(0, 0, 1);", + "//@ts-ignore", + "object.__light3D = pointLight;", + "//@ts-ignore", + "object.__pointLightAdapter = new PointLightAdapter(object, pointLight);", + "", + "const pointLight3DRenderer = new Light3DRenderer(object, object._instanceContainer, object.getInstanceContainer());", + "object._renderer = pointLight3DRenderer;", + "if (game.isInGameEdition && game.isInGameEdition()) {", + " const pointLightHelper = new PointLightHelper(object);", + " pointLightHelper.rotation.order = 'ZYX';", + " pointLightHelper.add(pointLight);", + " pointLight3DRenderer._threeGroup = pointLightHelper;", + " layer.getRenderer().add3DRendererObject(pointLightHelper);", + "}", + "else {", + " pointLight3DRenderer._threeGroup = pointLight;", + " layer.getRenderer().add3DRendererObject(pointLight);", + "}", + "", + "pointLight.updateMatrixWorld(true);", + "", + "// Allow to tween the light color.", + "//@ts-ignore", + "if (!object.setColor && !object.getColor) {", + " const prototype = Object.getPrototypeOf(object);", + " prototype.setColor = function(tint) {", + " this._setColor(tint);", + " this.__pointLightAdapter.setColor(tint);", + " }", + " prototype.getColor = function() {", + " return this._getColor(eventsFunctionContext);", + " }", + "}", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Light3D::PointLight3D::UpdateFromProperties" + }, + "parameters": [ + "Object", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onDestroy", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "/** @type {gdjs.CustomRuntimeObject} */", + "const object = objects[0];", + "// Here runtimeScene is the gdjs.CustomRuntimeObjectInstanceContainer inside the custom object.", + "const gameScene = object.getRuntimeScene();", + "", + "object.__light3D.dispose();", + "object.get3DRendererObject().dispose();", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onHotReloading", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Light3D::PointLight3D::UpdateFromProperties" + }, + "parameters": [ + "Object", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Update from properties.", + "fullName": "Update from properties", + "functionType": "Action", + "name": "UpdateFromProperties", + "private": true, + "sentence": "Update from properties of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Light3D::PointLight3D::SetColor" + }, + "parameters": [ + "Object", + "=", + "Color", + "" + ] + }, + { + "type": { + "value": "Light3D::PointLight3D::SetIntensity" + }, + "parameters": [ + "Object", + "=", + "Intensity", + "" + ] + }, + { + "type": { + "value": "Light3D::PointLight3D::SetDecay" + }, + "parameters": [ + "Object", + "=", + "Decay", + "" + ] + }, + { + "type": { + "value": "Light3D::PointLight3D::SetRange" + }, + "parameters": [ + "Object", + "=", + "Range", + "" + ] + }, + { + "type": { + "value": "Light3D::PointLight3D::SetShadowQuality" + }, + "parameters": [ + "Object", + "=", + "ShadowQuality", + "" + ] + }, + { + "type": { + "value": "Light3D::PointLight3D::SetShadowCameraNearPlane" + }, + "parameters": [ + "Object", + "=", + "ShadowCameraNearPlane", + "" + ] + }, + { + "type": { + "value": "Light3D::PointLight3D::SetShadowCameraFarPlane" + }, + "parameters": [ + "Object", + "=", + "ShadowCameraFarPlane", + "" + ] + }, + { + "type": { + "value": "Light3D::PointLight3D::SetShadowBias" + }, + "parameters": [ + "Object", + "=", + "ShadowBias", + "" + ] + }, + { + "type": { + "value": "Light3D::PointLight3D::UpdateHelper" + }, + "parameters": [ + "Object", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsCastingShadow", + "=", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "Light3D::PointLight3D::SetCastingShadow" + }, + "parameters": [ + "Object", + "no", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsCastingShadow", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "Light3D::PointLight3D::SetCastingShadow" + }, + "parameters": [ + "Object", + "yes", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "Update helper", + "functionType": "Action", + "name": "UpdateHelper", + "private": true, + "sentence": "Update graphical helper of _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const game = runtimeScene.getGame();", + "if (game.isInGameEdition && game.isInGameEdition()) {", + " const pointLightHelper = objects[0].get3DRendererObject();", + " pointLightHelper.update();", + "}", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the color of the light.", + "fullName": "Color", + "functionType": "ExpressionAndCondition", + "name": "Color", + "sentence": "the color", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnString" + }, + "parameters": [ + "Color" + ] + } + ] + } + ], + "expressionType": { + "type": "color" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Color", + "name": "SetColor", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "Color", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const color = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__pointLightAdapter.setColor(color);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the intensity of the light.", + "fullName": "Intensity", + "functionType": "ExpressionAndCondition", + "name": "Intensity", + "sentence": "the intensity", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Intensity" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Intensity", + "name": "SetIntensity", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Intensity", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__pointLightAdapter.setIntensity(value);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the decay of the light. The amount the light dims along the distance of the light.", + "fullName": "Decay", + "functionType": "ExpressionAndCondition", + "name": "Decay", + "sentence": "the decay", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Decay" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Decay", + "name": "SetDecay", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Decay", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__pointLightAdapter.setDecay(value);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Check if the light is casting shadows.", + "fullName": "Shadow casting", + "functionType": "Condition", + "group": "3D point light shadow configuration", + "name": "IsCastingShadow", + "sentence": "_PARAM0_ casting shadows", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "IsCastingShadow", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetReturnBoolean" + }, + "parameters": [ + "True" + ] + }, + { + "type": { + "value": "Light3D::PointLight3D::SetRange" + }, + "parameters": [ + "Object", + "=", + "Range", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "Change if the light is casting shadows.", + "fullName": "Shadow casting", + "functionType": "Action", + "group": "3D point light shadow configuration", + "name": "SetCastingShadow", + "sentence": "_PARAM0_ casting shadows: _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "False", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsCastingShadow", + "False", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BooleanVariable" + }, + "parameters": [ + "Value", + "True", + "" + ] + } + ], + "actions": [ + { + "type": { + "value": "SetBooleanVariable" + }, + "parameters": [ + "IsCastingShadow", + "True", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__pointLightAdapter.setCastingShadow(value);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + }, + { + "defaultValue": "yes", + "description": "Shadow casting", + "name": "Value", + "optional": true, + "type": "yesorno" + } + ], + "objectGroups": [] + }, + { + "description": "the shadow quality of the light.", + "fullName": "Shadow quality", + "functionType": "ExpressionAndCondition", + "group": "3D point light shadow configuration", + "name": "ShadowQuality", + "sentence": "the shadow quality", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnString" + }, + "parameters": [ + "ShadowQuality" + ] + } + ] + } + ], + "expressionType": { + "supplementaryInformation": "[\"Low\",\"Medium\",\"High\"]", + "type": "stringWithSelector" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "ShadowQuality", + "group": "3D point light shadow configuration", + "name": "SetShadowQuality", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetStringVariable" + }, + "parameters": [ + "ShadowQuality", + "=", + "Value" + ] + }, + { + "type": { + "value": "Light3D::PointLight3D::ApplyShadowBias" + }, + "parameters": [ + "Object", + "ShadowBias", + "ShadowQuality", + "" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__pointLightAdapter.setShadowQuality(value);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the shadow camera near plane of the light.", + "fullName": "Shadow camera near plane", + "functionType": "ExpressionAndCondition", + "group": "3D point light shadow configuration", + "name": "ShadowCameraNearPlane", + "sentence": "the shadow camera near plane", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ShadowCameraNearPlane" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "ShadowCameraNearPlane", + "group": "3D point light shadow configuration", + "name": "SetShadowCameraNearPlane", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ShadowCameraNearPlane", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__pointLightAdapter.setShadowCameraNearPlane(value);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Light3D::PointLight3D::SetRange" + }, + "parameters": [ + "Object", + "=", + "Range", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the shadow camera far plane of the light.", + "fullName": "Shadow camera far plane", + "functionType": "ExpressionAndCondition", + "group": "3D point light shadow configuration", + "name": "ShadowCameraFarPlane", + "sentence": "the shadow camera far plane", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ShadowCameraFarPlane" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "ShadowCameraFarPlane", + "group": "3D point light shadow configuration", + "name": "SetShadowCameraFarPlane", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ShadowCameraFarPlane", + "=", + "Value" + ] + }, + { + "type": { + "value": "Light3D::PointLight3D::ApplyShadowCameraFarPlane" + }, + "parameters": [ + "Object", + "min(Value, Range)", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "description": "the range of the light. 0 means no limit.", + "fullName": "Range", + "functionType": "ExpressionAndCondition", + "name": "Range", + "sentence": "the range", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "Range" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "Range", + "name": "SetRange", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "Range", + "=", + "Value" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__pointLightAdapter.setRange(value);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Three.js reduces the far plane to match the light range.\nSo, we need to set it again or it will stay at the lowest value the range took.\nWe do the min() on our side to in order:\n- to avoid a side effect when Three.js is upgraded\n- because Three.js keeps the old value in cache and doesn't apply it back unless we set the lower value explicitly ourselves." + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "Light3D::PointLight3D::ApplyShadowCameraFarPlane" + }, + "parameters": [ + "Object", + "min(Value, ShadowCameraFarPlane)", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "Apply shadow camera far plane", + "functionType": "Action", + "group": "3D point light shadow configuration", + "name": "ApplyShadowCameraFarPlane", + "private": true, + "sentence": "Apply shadow camera far plane of _PARAM0_ to _PARAM1_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "\r", + "object.__pointLightAdapter.setShadowCameraFarPlane(value);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + }, + { + "description": "Value", + "name": "Value", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "description": "the shadow bias of the light. Use this to avoid \"shadow acne\" due to depth buffer precision. Choose a value small enough like 0.001 to avoid creating distance between shadows and objects but not too small to avoid shadow glitches on low/medium quality. This value is used for high quality, and multiplied by 2 for medium quality and 4 for low quality.", + "fullName": "Shadow bias", + "functionType": "ExpressionAndCondition", + "group": "3D point light shadow configuration", + "name": "ShadowBias", + "sentence": "the shadow bias", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetReturnNumber" + }, + "parameters": [ + "ShadowBias" + ] + } + ] + } + ], + "expressionType": { + "type": "expression" + }, + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "ActionWithOperator", + "getterName": "ShadowBias", + "group": "3D point light shadow configuration", + "name": "SetShadowBias", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SetNumberVariable" + }, + "parameters": [ + "ShadowBias", + "=", + "Value" + ] + }, + { + "type": { + "value": "Light3D::PointLight3D::ApplyShadowBias" + }, + "parameters": [ + "Object", + "Value", + "ShadowQuality", + "" + ] + } + ] + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + } + ], + "objectGroups": [] + }, + { + "fullName": "Apply shadow bias", + "functionType": "Action", + "group": "3D point light shadow configuration", + "name": "ApplyShadowBias", + "private": true, + "sentence": "Apply shadow bias of _PARAM0_ to _PARAM1_ for a _PARAM2_ quality", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];\r", + "const value = eventsFunctionContext.getArgument(\"Value\");\r", + "const quality = eventsFunctionContext.getArgument(\"Quality\");\r", + "\r", + "object.__pointLightAdapter.setShadowBias(value, quality);\r", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "supplementaryInformation": "Light3D::PointLight3D", + "type": "object" + }, + { + "description": "Value", + "name": "Value", + "type": "expression" + }, + { + "description": "Quality", + "name": "Quality", + "type": "string" + } + ], + "objectGroups": [] + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onCreated" + }, + { + "functionName": "onDestroy" + }, + { + "functionName": "onHotReloading" + }, + { + "functionName": "UpdateFromProperties" + }, + { + "functionName": "UpdateHelper" + }, + { + "functionName": "Color" + }, + { + "functionName": "SetColor" + }, + { + "functionName": "Intensity" + }, + { + "functionName": "SetIntensity" + }, + { + "functionName": "Decay" + }, + { + "functionName": "SetDecay" + }, + { + "functionName": "Range" + }, + { + "functionName": "SetRange" + }, + { + "folderName": "3D point light shadow configuration", + "children": [ + { + "functionName": "IsCastingShadow" + }, + { + "functionName": "SetCastingShadow" + }, + { + "functionName": "ShadowQuality" + }, + { + "functionName": "SetShadowQuality" + }, + { + "functionName": "ShadowCameraNearPlane" + }, + { + "functionName": "SetShadowCameraNearPlane" + }, + { + "functionName": "ShadowCameraFarPlane" + }, + { + "functionName": "SetShadowCameraFarPlane" + }, + { + "functionName": "ApplyShadowCameraFarPlane" + }, + { + "functionName": "ShadowBias" + }, + { + "functionName": "SetShadowBias" + }, + { + "functionName": "ApplyShadowBias" + } + ] + } + ] + }, + "propertyDescriptors": [ + { + "value": "255;255;255", + "type": "Color", + "label": "Color", + "name": "Color" + }, + { + "value": "1", + "type": "Number", + "label": "Intensity", + "name": "Intensity" + }, + { + "value": "2", + "type": "Number", + "label": "Decay", + "description": "The amount the light dims along the distance of the light.", + "name": "Decay" + }, + { + "value": "true", + "type": "Boolean", + "label": "Shadow casting", + "group": "Shadow", + "name": "IsCastingShadow" + }, + { + "value": "Medium", + "type": "Choice", + "label": "Shadow quality", + "group": "Shadow", + "choices": [ + { + "label": "", + "value": "Low" + }, + { + "label": "", + "value": "Medium" + }, + { + "label": "", + "value": "High" + } + ], + "name": "ShadowQuality" + }, + { + "value": "20", + "type": "Number", + "unit": "Pixel", + "label": "Shadow camera near plane", + "group": "Shadow", + "advanced": true, + "name": "ShadowCameraNearPlane" + }, + { + "value": "2000", + "type": "Number", + "unit": "Pixel", + "label": "Shadow camera far plane", + "group": "Shadow", + "advanced": true, + "name": "ShadowCameraFarPlane" + }, + { + "value": "2000", + "type": "Number", + "unit": "Pixel", + "label": "Range", + "description": "0 means no limit.", + "name": "Range" + }, + { + "value": "0", + "type": "Number", + "label": "Shadow Bias", + "description": "Use this to avoid \"shadow acne\" due to depth buffer precision. Choose a value small enough like 0.001 to avoid creating distance between shadows and objects but not too small to avoid shadow glitches on low/medium quality. This value is used for high quality, and multiplied by 2 for medium quality and 4 for low quality.", + "group": "Shadow", + "advanced": true, + "name": "ShadowBias" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "propertyName": "Color" + }, + { + "propertyName": "Intensity" + }, + { + "propertyName": "Decay" + }, + { + "propertyName": "Range" + }, + { + "folderName": "Shadow", + "children": [ + { + "propertyName": "IsCastingShadow" + }, + { + "propertyName": "ShadowQuality" + }, + { + "propertyName": "ShadowCameraNearPlane" + }, + { + "propertyName": "ShadowCameraFarPlane" + }, + { + "propertyName": "ShadowBias" + } + ] + } + ] + } + } + ] + } + ], + "tests": [ + { + "name": "The sun lights the scene and casts shadows", + "description": "The directional light of the scene reaches the 3D renderer with shadow casting on, and lights the props.", + "type": "gameplay", + "source": [ + "// Look at the lights the 3D renderer can actually see, the way three.js does:", + "// hidden subtrees are skipped entirely, so this agrees with what the shaders", + "// were given rather than with what is in the scene graph.", + "const readLights = () => {", + " const threeScene = harness.getRuntimeLayer('').getRenderer().getThreeScene();", + " const lights = { point: [], spot: [], spotWithMap: [], directional: [], shadows: 0 };", + " if (!threeScene) return lights;", + " const walk = (object) => {", + " if (!object.visible) return;", + " if (object.isLight) {", + " const colour = object.color ? object.color.getHexString() : '';", + " if (object.isSpotLight) lights[object.map ? 'spotWithMap' : 'spot'].push(colour);", + " else if (object.isPointLight) lights.point.push(colour);", + " else if (object.isDirectionalLight) lights.directional.push(colour);", + " if (object.castShadow) lights.shadows++;", + " }", + " for (const child of object.children) walk(child);", + " };", + " walk(threeScene);", + " return lights;", + "};", + "const describe = (l) => JSON.stringify({ point: l.point.length,", + " spot: l.spot.length, spotWithMap: l.spotWithMap.length,", + " directional: l.directional.length, shadows: l.shadows });", + "", + "await harness.goToScene('Sun and Shadows');", + "await harness.stepFrames(10);", + "", + "const lights = readLights();", + "console.log('lights=' + describe(lights));", + "harness.assert(lights.directional.length === 1,", + " 'Exactly one directional light reaches the renderer (found ' + lights.directional.length + ').');", + "harness.assert(lights.shadows >= 1, 'The directional light casts a shadow.');", + "harness.assert(lights.point.length === 0 && lights.spot.length === 0,", + " 'This scene is lit by the sun alone.');", + "", + "harness.assert(harness.getObjects('Crate').length === 6, 'The six crates are in the scene.');", + "harness.assert(!!harness.getObjects('Ground')[0], 'The ground is in the scene.');", + "await harness.takeScreenshot('sun and shadows');" + ] + }, + { + "name": "Point lights light the scene at night", + "description": "The three point lights reach the 3D renderer, keep the colour each was given, and stay lit when one of them moves.", + "type": "gameplay", + "source": [ + "// Look at the lights the 3D renderer can actually see, the way three.js does:", + "// hidden subtrees are skipped entirely, so this agrees with what the shaders", + "// were given rather than with what is in the scene graph.", + "const readLights = () => {", + " const threeScene = harness.getRuntimeLayer('').getRenderer().getThreeScene();", + " const lights = { point: [], spot: [], spotWithMap: [], directional: [], shadows: 0 };", + " if (!threeScene) return lights;", + " const walk = (object) => {", + " if (!object.visible) return;", + " if (object.isLight) {", + " const colour = object.color ? object.color.getHexString() : '';", + " if (object.isSpotLight) lights[object.map ? 'spotWithMap' : 'spot'].push(colour);", + " else if (object.isPointLight) lights.point.push(colour);", + " else if (object.isDirectionalLight) lights.directional.push(colour);", + " if (object.castShadow) lights.shadows++;", + " }", + " for (const child of object.children) walk(child);", + " };", + " walk(threeScene);", + " return lights;", + "};", + "const describe = (l) => JSON.stringify({ point: l.point.length,", + " spot: l.spot.length, spotWithMap: l.spotWithMap.length,", + " directional: l.directional.length, shadows: l.shadows });", + "", + "await harness.goToScene('Point Lights');", + "await harness.stepFrames(10);", + "", + "const lights = readLights();", + "console.log('lights=' + describe(lights));", + "console.log('pointColours=' + JSON.stringify(lights.point.slice().sort()));", + "harness.assert(lights.point.length === 3,", + " 'All three point lights reach the renderer (found ' + lights.point.length + ').');", + "harness.assert(lights.spot.length === 0, 'No spot light is lit in this scene.');", + "harness.assert(lights.shadows >= 1, 'At least one point light casts a shadow.');", + "// Each light is a different object with its own colour: if the colour never", + "// reached the renderer they would all come back white.", + "harness.assert(new Set(lights.point).size === 3,", + " 'Each point light keeps its own colour (' + lights.point.join(', ') + ').');", + "await harness.takeScreenshot('three coloured point lights');", + "", + "// The budget is recomputed every frame, so a light that moves must stay lit.", + "const warm = harness.getObjects('PointLightWarm')[0];", + "harness.setObjectPosition(warm.id, 0, -680, 220);", + "await harness.stepFrames(10);", + "harness.assert(readLights().point.length === 3,", + " 'The point lights stay lit after one of them moves.');", + "await harness.takeScreenshot('after moving one point light');" + ] + }, + { + "name": "Spot lights light the scene and cast shadows", + "description": "Both spot lights reach the 3D renderer as spot lights, keep their own colour, and cast shadows.", + "type": "gameplay", + "source": [ + "// Look at the lights the 3D renderer can actually see, the way three.js does:", + "// hidden subtrees are skipped entirely, so this agrees with what the shaders", + "// were given rather than with what is in the scene graph.", + "const readLights = () => {", + " const threeScene = harness.getRuntimeLayer('').getRenderer().getThreeScene();", + " const lights = { point: [], spot: [], spotWithMap: [], directional: [], shadows: 0 };", + " if (!threeScene) return lights;", + " const walk = (object) => {", + " if (!object.visible) return;", + " if (object.isLight) {", + " const colour = object.color ? object.color.getHexString() : '';", + " if (object.isSpotLight) lights[object.map ? 'spotWithMap' : 'spot'].push(colour);", + " else if (object.isPointLight) lights.point.push(colour);", + " else if (object.isDirectionalLight) lights.directional.push(colour);", + " if (object.castShadow) lights.shadows++;", + " }", + " for (const child of object.children) walk(child);", + " };", + " walk(threeScene);", + " return lights;", + "};", + "const describe = (l) => JSON.stringify({ point: l.point.length,", + " spot: l.spot.length, spotWithMap: l.spotWithMap.length,", + " directional: l.directional.length, shadows: l.shadows });", + "", + "await harness.goToScene('Spot Lights');", + "await harness.stepFrames(10);", + "", + "const lights = readLights();", + "console.log('lights=' + describe(lights));", + "const spots = lights.spot.concat(lights.spotWithMap);", + "harness.assert(spots.length === 2,", + " 'Both spot lights reach the renderer (found ' + spots.length + ').');", + "harness.assert(lights.point.length === 0, 'No point light is lit in this scene.');", + "harness.assert(lights.shadows >= 1, 'At least one spot light casts a shadow.');", + "harness.assert(new Set(spots).size === 2,", + " 'Each spot light keeps its own colour (' + spots.join(', ') + ').');", + "await harness.takeScreenshot('two spot lights with shadows');" + ] + }, + { + "name": "Mixed light kinds stay within a stable budget", + "description": "With more lights placed than one budget can hold, and of two kinds the shaders count separately (point lights and spot lights), the number of each kind that is lit must stay the same while the lights move. A count that moves makes the renderer compile a new shader, which drops a frame.", + "type": "gameplay", + "source": [ + "// Look at the lights the 3D renderer can actually see, the way three.js does:", + "// hidden subtrees are skipped entirely, so this agrees with what the shaders", + "// were given rather than with what is in the scene graph.", + "const readLights = () => {", + " const threeScene = harness.getRuntimeLayer('').getRenderer().getThreeScene();", + " const lights = { point: [], spot: [], spotWithMap: [], directional: [], shadows: 0 };", + " if (!threeScene) return lights;", + " const walk = (object) => {", + " if (!object.visible) return;", + " if (object.isLight) {", + " const colour = object.color ? object.color.getHexString() : '';", + " if (object.isSpotLight) lights[object.map ? 'spotWithMap' : 'spot'].push(colour);", + " else if (object.isPointLight) lights.point.push(colour);", + " else if (object.isDirectionalLight) lights.directional.push(colour);", + " if (object.castShadow) lights.shadows++;", + " }", + " for (const child of object.children) walk(child);", + " };", + " walk(threeScene);", + " return lights;", + "};", + "const describe = (l) => JSON.stringify({ point: l.point.length,", + " spot: l.spot.length, spotWithMap: l.spotWithMap.length,", + " directional: l.directional.length, shadows: l.shadows });", + "", + "await harness.goToScene('Mixed Lights');", + "await harness.stepFrames(10);", + "", + "const names = ['MixedPoint', 'MixedPointShadow', 'MixedSpot', 'MixedSpotShadow'];", + "const placed = names.reduce((all, n) => all.concat(harness.getObjects(n)), []);", + "harness.assert(placed.length === 26, '26 lights are placed (' + placed.length + ').');", + "", + "const first = readLights();", + "console.log('lights=' + describe(first));", + "harness.assert(first.point.length > 0, 'Point lights are lit.');", + "harness.assert(first.spot.length > 0, 'Spot lights are lit.');", + "console.log('litTotal=' + (first.point.length + first.spot.length) +", + " ' of ' + placed.length + ' placed');", + "await harness.takeScreenshot('mixed light kinds at once');", + "", + "// Sweep the camera across the field, which is what a player does and what", + "// reshuffles the whole distance ordering: which lights are nearest changes", + "// completely. How many of each kind are lit must not change with it - a", + "// count that moves makes the renderer compile another shader.", + "const scene = harness.getCurrentRuntimeScene();", + "const seen = new Set();", + "for (let step = 0; step < 8; step++) {", + " const t = step / 7;", + " gdjs.evtTools.camera.setCameraX(scene, -900 + t * 1800, '', 0);", + " gdjs.evtTools.camera.setCameraY(scene, 1450 - t * 700, '', 0);", + " await harness.stepFrames(3);", + " const l = readLights();", + " seen.add(l.point.length + '/' + l.spot.length + '/' + l.spotWithMap.length +", + " '/' + l.shadows);", + "}", + "console.log('combinations=' + JSON.stringify([...seen]));", + "harness.assert(seen.size === 1,", + " 'The number of lights of each kind stays the same as the camera moves (saw ' +", + " seen.size + ': ' + [...seen].join(', ') + ').');", + "await harness.takeScreenshot('budget held while the camera swept');" + ] + }, + { + "name": "One light kind gets the whole device budget", + "description": "Eight shadow casting point lights, and nothing else: a scene that uses a single light kind must be given the device budget for that kind rather than a third of it, so it keeps as many shadow casters as the device really allows. The counts must also stay put while the camera moves, or the renderer compiles another shader and drops a frame.", + "type": "gameplay", + "source": [ + "// Look at the lights the 3D renderer can actually see, the way three.js does:", + "// hidden subtrees are skipped entirely, so this agrees with what the shaders", + "// were given rather than with what is in the scene graph.", + "const readLights = () => {", + " const threeScene = harness.getRuntimeLayer('').getRenderer().getThreeScene();", + " const lights = { point: 0, spot: 0, spotWithMap: 0, directional: 0, shadows: 0 };", + " if (!threeScene) return lights;", + " const walk = (object) => {", + " if (!object.visible) return;", + " if (object.isLight) {", + " if (object.isSpotLight) lights[object.map ? 'spotWithMap' : 'spot']++;", + " else if (object.isPointLight) lights.point++;", + " else if (object.isDirectionalLight) lights.directional++;", + " if (object.castShadow) lights.shadows++;", + " }", + " for (const child of object.children) walk(child);", + " };", + " walk(threeScene);", + " return lights;", + "};", + "", + "await harness.goToScene('Crowded Point Lights');", + "await harness.stepFrames(10);", + "", + "const placed = harness.getObjects('CrowdedPointShadow');", + "harness.assert(placed.length === 8,", + " '8 shadow casting point lights are placed (' + placed.length + ').');", + "", + "const lights = readLights();", + "console.log('lights=' + JSON.stringify(lights));", + "", + "// Every light here is a point light, so three.js counts them all under the", + "// same defines and the whole budget for that kind is theirs. A budget shared", + "// between kinds that the scene never uses would hold most of it back.", + "harness.assert(lights.spot === 0 && lights.spotWithMap === 0 &&", + " lights.directional === 0,", + " 'Only point lights are lit, so a single kind holds the budget (' +", + " JSON.stringify(lights) + ').');", + "harness.assert(lights.point === 8,", + " 'All 8 point lights are lit (' + lights.point + ').');", + "", + "// Three is the floor across every conforming WebGL2 device: 15 varyings", + "// guaranteed, less what the geometry spends, all of it for this one kind.", + "// Splitting the same budget three ways - once per kind the engine knows of,", + "// used or not - would leave only one or two here.", + "harness.assert(lights.shadows >= 3,", + " 'At least 3 of them cast a shadow, which needs the budget to go to the kind actually in use (' + lights.shadows + ').');", + "await harness.takeScreenshot('eight point lights, shadows up to the budget');", + "", + "// The same stability property the mixed scene checks, on one kind: moving the", + "// camera reshuffles which lights are nearest, and the counts compiled into", + "// the shaders must not follow.", + "const scene = harness.getCurrentRuntimeScene();", + "const seen = new Set();", + "for (let step = 0; step < 8; step++) {", + " const t = step / 7;", + " gdjs.evtTools.camera.setCameraX(scene, -900 + t * 1800, '', 0);", + " gdjs.evtTools.camera.setCameraY(scene, 1450 - t * 700, '', 0);", + " await harness.stepFrames(3);", + " const l = readLights();", + " seen.add(l.point + '/' + l.shadows);", + "}", + "console.log('combinations=' + JSON.stringify([...seen]));", + "harness.assert(seen.size === 1,", + " 'The number of lit and shadow casting point lights stays the same as the ' +", + " 'camera moves (saw ' + seen.size + ': ' + [...seen].join(', ') + ').');", + "await harness.takeScreenshot('one kind held steady while the camera swept');" + ] + } + ] +} diff --git a/examples/3d-light-playground/README.md b/examples/3d-light-playground/README.md new file mode 100644 index 000000000..0cfb40317 --- /dev/null +++ b/examples/3d-light-playground/README.md @@ -0,0 +1,13 @@ +# 3D Light Playground + +A playground for GDevelop's 3D lights, with one scene per kind of light so each can +be looked at on its own. + +- **Sun and Shadows** — the directional light of the scene, casting shadows across + the ground, the crates and the backdrop. +- **Point Lights** — three point lights, each with its own colour, lighting an + otherwise dark scene and casting shadows away from themselves. +- **Spot Lights** — two spot lights aimed at the ground, showing the cone, the + falloff towards its edge, and the shadows underneath. +- **Mixed Lights** — twenty-six lights of two kinds at once (point and spot), + more than one shared budget can hold, to see how the budget behaves. diff --git a/examples/3d-light-playground/assets/LightPlaygroundSurface.png b/examples/3d-light-playground/assets/LightPlaygroundSurface.png new file mode 100644 index 000000000..2ec0cc395 Binary files /dev/null and b/examples/3d-light-playground/assets/LightPlaygroundSurface.png differ